计数排序,第一次扫描获得0,1,2的数量,第二次赋值。
题目想只用一次扫描完成。先贴上two-pass。
class Solution {
public:
void sortColors(int A[], int n) {
int count[3]={0,0,0};
for(int i=0;i<n;i++)
count[A[i]]++;
for(int i=0;i<count[0];i++)
A[i] = 0;
for(int i=count[0];i<count[0]+count[1];i++)
A[i] = 1;
for(int i=count[0]+count[1];i<n;i++)
A[i] = 2;
}
};
但凡要求一次线性扫描的,十有八九要用到前后两个index,因为这题只有0,1,2三种情况,所以设置index i指向头,j指向尾部最后一个不是2的位置。
跟快排的partition有些类似。 cur向右扫描,do
case A: 遇到1就继续
case B: 遇到0就设置当前A[cur] 为1,A[i]为0,i++,cur++继续。(这个case不能先设A[i]=0再设A[cur]=1,必须反过来,这是i和cur重叠造成的副作用)
case C: 遇到2的话就和A[j](此时A[j]为0或1)交换,j跳过所有2,继续指向尾部第一个非2。此时A[cur]为0或者1,所以继续case A或B。
直到cur > j 结束。
class Solution {
public:
void sortColors(int A[], int n) {
int i = -1, cur = 0, j = n-1;
while(A[j]==2)
--j;
while(A[cur]==0){
++i;
++cur;
}
while(cur<=j){
if(A[cur]==1)
++cur;
else if(A[cur]==0){
A[cur++] = 1;
A[++i] = 0;
}
else{
int tmp = A[j];
A[j] = 2;
A[cur] = tmp;
--j;
while(A[j]==2)
--j;
}
}
}
};