输入: 数组 nums,元素只包含 0(红)、1(白)、2(蓝)。
要求: 在原地对 nums 排序,相同颜色相邻,顺序为红(0)、白(1)、蓝(2),不能使用 sort。
输出: 排序后的数组 。
思路1:两次双指针处理,第一次处理0与非0元素,得到0与非0的分界点,再处理剩余元素中的1与2。
思路2:空间换时间,一次遍历,分三组,但是要求原地排序,那没事了,不可行。
思路3:
-
0指针从序号0开始,记录下一个0元素要放在哪里
-
2指针从序号n-1开始,记录下一个2元素放在哪里
-
遍历指针,从头遍历到位,且遍历指针不大于2指针。
-
从头开始遍历数组,找到第一个非0元素,令该位置为0指针起点
-
从尾开始遍历数组,找到第一个非2元素,令该位置为2指针起点
-
从0指针起点开始遍历数组,循环范围 小于等于 2指针序号
-
开始遍历,遇0就跟0指针交换,0指针进1;遇2就跟2指针交换,2指针减1,而且得检查2指针交换回来的数是什么。
思路4:三指针法
-
定义指针:
-
-
p0:指向下一个 0 应放置的位置;
-
curr:当前遍历位置;
-
p2:指向下一个 2 应放置的位置。
-
-
循环条件:curr <= p2。
-
规则:
-
若 nums[curr] == 0 → 与 nums[p0] 交换,p0++,curr++。
-
若 nums[curr] == 2 → 与 nums[p2] 交换,p2--,curr 不动。
-
若 nums[curr] == 1 → curr++。
-
时间复杂度:O(n),空间复杂度:O(1)。
class Solution {
public:
void sortColors(vector<int>& nums) {
int n = nums.size();
int p0 = 0;
while (p0 < n && nums[p0] == 0) {
p0++;
}
if (p0 >= n) {
return;
}
int p2 = n - 1;
while (p2 >= 0 && nums[p2] == 2) {
p2--;
}
if (p2 <= 0) {
return;
}
for (int i = p0; i <= p2; i++) {
if (nums[i] == 0) {
nums[i] = nums[p0];
nums[p0++] = 0;
}
else if (nums[i] == 2) {
nums[i] = nums[p2];
nums[p2--] = 2;
i--;
}
}
return;
}
};
class Solution {
public:
void sortColors(vector<int>& nums) {
int n = nums.size();
int p0 = 0;
int p1 = p0;
int p2 = n -1;
while (p1 <= p2) {
if (nums[p1] == 0) {
swap(nums[p0++], nums[p1++]);
}
else if (nums[p1] == 1) {
p1++;
}
else if (nums[p1] == 2) {
swap(nums[p2--], nums[p1]);
}
}
return;
}
};

212

被折叠的 条评论
为什么被折叠?



