题目描述
知识点
排序、数组、双指针
结果
实现
码前思考
- 题目要求
in-place
,而且还要尝试是否能够come up with a one-pass algorithm using only constant space
; in-place
我还可以,但是后面那个条件我有点想不到啊,所以只有暴力计数了;
代码实现
暴力计数
//想不出好的办法,直接传统吧,计数走起,后面再补
class Solution {
public:
void sortColors(vector<int>& nums) {
int cnt0=0;
int cnt1=0;
int cnt2=0;
for(int i=0;i<nums.size();i++){
switch(nums[i]){
case 0:
cnt0++;
break;
case 1:
cnt1++;
break;
case 2:
cnt2++;
break;
default:
;
}
}
int cnt = 0;
for(int i=0;i<cnt0;i++){
nums[cnt] = 0;
cnt++;
}
for(int i=0;i<cnt1;i++){
nums[cnt] = 1;
cnt++;
}
for(int i=0;i<cnt2;i++){
nums[cnt] = 2;
cnt++;
}
}
};
高级做法——双指针
参考的题解是官方的题解——颜色分类
//参考标准答案,使用双指针进行解题
class Solution {
public:
void sortColors(vector<int>& nums) {
int p0=0;
int p2=nums.size()-1;
int curr=0;
while(curr <= p2){
//cout<<curr<<endl;
if(nums[curr] == 0){
nums[curr] = nums[p0];
nums[p0] = 0;
//移动两个
p0++;
curr++;
}else if(nums[curr] == 2){
nums[curr] = nums[p2];
nums[p2] = 2;
p2--;
}else{
curr++;
}
}
}
};
码后反思
- 这道题最大的作用就是让我知道了怎么使用双指针解这道题,太妙了!
p0
代表0的右边界,p2
代表2的左边界。妙不可言;- 对于
p0
和curr
交换,两者都要加加; - 对于
p2
和curr
交换,只需要减减p2
,不需要移动curr
,因为交换的值可能还需要再进行交换。这是这道题目比较难想的一个地方。
二刷代码
二刷的时候不小心看见了提示,所以知道得用左右指针来解题,知道left
表示0
的边界,right
表示1
的边界。但是还是没有搞清楚curp
与right
交换之后应该进行什么操作才对!这个其实讲道理很难讲,还是要自己多举几个例子好好理解!
//采用指针的方法进行解题,这里有两个边界,同时也有一个表示当前处理的元素
class Solution {
public:
void sortColors(vector<int>& nums) {
int left=0;
int curp=0;
int right=nums.size()-1;
while(curp<=right){
if(nums[curp]==0){
swap(nums[left],nums[curp]);
left++;
curp++;
}else if(nums[curp]==2){
swap(nums[right],nums[curp]);
right--;
}else{
curp++;
}
// for(auto num : nums){
// printf("%d ",num);
// }
// printf("\n");
}
}
};
这个解法有个隐含的信息——left
与curp
之间应该全部是1。