给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
注意: 不能使用代码库中的排序函数来解决这道题。
示例:
输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]
无脑的解法:使用内置排序算法
计数排序解法:
第一遍遍历:分别计算有多少个0、1、2
第二遍:对原数组分别填充计算所得的0、1、2个数
实现:
class Solution {
public:
void sortColors(vector<int>& nums) {
int redNums = 0; // 存储有多少个0
int whiteNums = 0; // 有多少个1
int blueNums = 0; // 有多少个2
for(int i = 0; i < nums.size(); i++) {
if(nums[i] == 0) {
redNums++;
} else if (nums[i] == 1) {
whiteNums++;
} else {
blueNums++;
}
}
int i = 0;
// 填充0
while(redNums > 0) {
nums[i] = 0;
redNums--;
i++;
}
// 填充1
while(whiteNums > 0) {
nums[i] = 1;
whiteNums--;
i++;
}
// 填充2
while(blueNums > 0) {
nums[i] = 2;
blueNums--;
i++;
}
}
};
多指针解法:
使用两个指针分别指向跟0和2相邻接的一位,用一个遍历指针遍历数组,当遍历指针大于等于指向2的指针的位置时,结束遍历,排序完成
实现:
class Solution {
public:
void sortColors(vector<int>& nums) {
int redPoint = 0; // 指向跟0相邻接的一位,初始化为0
int bluePoint = nums.size() - 1; // 指向跟2相邻接的一位,初始化为最后一个位置
int current = 0; // 遍历指针
// 遍历结束/完成条件 遍历指针大于跟2相邻的指针
while(current <= bluePoint) {
if(nums[current] == 0) { // 如果当前位是0,则跟邻接0的指针交换
nums[current] = nums[redPoint];
nums[redPoint] = 0;
redPoint++;
current++;
} else if(nums[current] == 1){ // 如果是1,则继续遍历
current++;
} else if(nums[current] == 2) { // 如果当前位是2,则跟邻接2的指针交换
nums[current] = nums[bluePoint];
nums[bluePoint] = 2;
bluePoint--;
}
}
}
};
更详细的解读及动画演示,请参考官方题解