思路:
可以通过计数0,1,2的个数,然后按照个数直接个nums重新赋值覆盖原来的值即可。
class Solution {
public:
void sortColors(vector<int>& nums) {
int n=nums.size();
if(n==1) return;
int n0=0,n1=0,n2=0;
for(auto& num:nums){
if(num==0) n0++;
else if(num==1) n1++;
else n2++;
}
int i=0;
while(n0>0) {
nums[i++]=0;
n0--;
}
while(n1>0){
nums[i++]=1;
n1--;
}
while(n2>0){
nums[i++]=2;
n2--;
}
return;
}
};
单指针的方法,定义一个指针p,需要两个循环,一个循环是将0全部放在数组前面,另一个循环将1放在0后面,结束后自然2排在1后面了。
遍历nums,判断nums[i]是否为0,如果是0就将p指的元素和它交换位置,那么就能把0放到前面了,然后指针在加一。否则就i++,再继续。所以只有当0和其他数字交换的时候指针才会移动,那么指针会一直指向0应该在的位置上,所以i遍历到后面的元素0直接和指针交换即可。
对元素1同理,当0填满前面的位置后,指针就指向1应该在的位置了,同时因为0的交换,1和2都被放在0后面的位置了.
class Solution {
public:
void sortColors(vector<int>& nums) {
int n=nums.size();
if(n==1) return;
int p=0;
for(int i=0;i<n;i++){
if(nums[i]==0){
swap(nums[i],nums[p]);
p++;
}
}
for(int i=p;i<n;i++){
if(nums[i]==1){
swap(nums[i],nums[p]);
p++;
}
}
return;
}
};
双指针的方法就是一个循环解决0和1的位置。通过两个指针,一个p0用来和0交换,一个p1用来和1交换,当0和p0交换后 要判断p1是否大于p0,如果大于,那么就还得交换i和p1的元素,原因是i可能遇到0,然后p0指到的是1,这样交换把放在0区域的1给换出去,而此时p1大于p0说明p1不会再影响前面已经交换过的0,这时候如果i不和p1交换,那么被换出去的1就要丢失了因为i下次就要++跳过去了。然后,p0++,p1也得加,否则遇到1和p1交换后,就把前面换到的0给换出去了,也因为1是放在0后面所以也要跟着移动。如果nums[i]是1就直接和p1交换即可。
代码:
class Solution {
public:
void sortColors(vector<int>& nums) {
int n=nums.size();
if(n==1) return;
int p0=0,p1=0;
for(int i=0;i<n;++i){
if(nums[i]==1){
swap(nums[i],nums[p1]);
p1++;
}
else if(nums[i]==0){
swap(nums[i],nums[p0]);
if(p1>p0) swap(nums[i],nums[p1]);
p0++;
p1++;
}
}
return;
}
};
另一个是从p0和p2入手,p2从右到左遍历,那么只需要i<=p2即可。对于p2交换元素来说,可能i和p2都指向2,交换后i++会导致一个2的丢失,所以我们需要while交换i的元素直到i指向的不再为2。对于p0来说还是遇到0就和p0交换即可。
class Solution {
public:
void sortColors(vector<int>& nums) {
int n=nums.size();
if(n==1) return;
int p0=0,p2=n-1;
for(int i=0;i<=p2;++i){
while(i<=p2&&nums[i]==2){
swap(nums[i],nums[p2]);
p2--;
}
if(nums[i]==0){
swap(nums[i],nums[p0]);
p0++;
}
}
return;
}
};