其实这个Follow up说的也很好哇,计数排序
A rather straight forward solution is a two-pass algorithm using counting sort.
First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's.
1 void sortColors(int A[], int n) { 2 if(A==NULL||n<=0) 3 return; 4 int count=3; 5 int C[count]; 6 int i,j; 7 for(i=0;i<count;++i) 8 C[i]=0; 9 for(i=0;i<n;++i){ 10 j=A[i]; 11 C[j]++; 12 } 13 j=n-1; 14 for(i=count-1;i>=0;--i){ 15 while(C[i]){ 16 A[j]=i; 17 C[i]--; 18 j--;//这个别忘了 19 } 20 } 21 }
AC
如果只遍历一遍的话,我觉得快排挺合适的,但是万一数组中没有1呢,是不是要先扫描一下,看看是不是有1,那不能,如果那样的话,也要扫两遍的。那怎么办呢?
管他三七二十一呢,就把数组中的最后一个存到一个变量中先,然后把它设为1,然后等所有的都排好后,就把变量中的那个放到那个位置,
如果是 0,0,0,*,1,1,1,2 那么原来数组中是0或1都可以,可是如果是2的话就不行了
如果是 0,0,0,1,1,1,*,2 那么原来数组中是2或1都可以,可是如果是0的话就不行了
如果是 0,0,0,1,1,1,*,1,1,1,1,2 那么原来数组中是1可以,可是如果是0或者2的话就不行了
可见,自己对快排的过程是不清楚的,找时间也得在仔细看看快排哇?????????????????????????
在 http://tech-wonderland.net/blog/leetcode-sort-colors.html 上看到了一个好方法
By keeping three pointers, i (=0), j (= n -1), k, i points to the front part of the array while j points to the back end of the array, use k to scan through the whole array, when encountering 0, swap A[i] and A[k], when encountering 2, swap A[j] and A[k] and move the pointers i, j, k correspondingly, after finishing one pass scan, all the elements before i are expected to be 0, all the elements after j are expected to be 2, all the elements between i and j are 1.
1 void swap(int &a,int &b){ 2 int tmp; 3 tmp=a; 4 a=b; 5 b=tmp; 6 } 7 void sortColors(int A[], int n) { 8 if(A==NULL||n<=0) 9 return; 10 int i,j,k; 11 i=0; 12 j=n-1; 13 k=0; 14 while(k<=j){ 15 if(A[k]==0){ 16 swap(A[i],A[k]); 17 i++; 18 } 19 if(A[k]==2){ 20 swap(A[k],A[j]); 21 j--; 22 } 23 k++; 24 } 25 }
Status: Wrong Answer
Input:[1,2,0]
Output:[1,0,2]
Expected:[0,1,2]
http://tech-wonderland.net/blog/leetcode-sort-colors.html中还说道:
Tips and Divergent thinking:
Be careful when moving the pointers: when to just move j e.g j–, when to just move i e.g. i++, when to just move k, k++, when to move both i and k, or move both j and k.
如果把23行改为
if(A[k]!=0&&A[k]!=2) k++;
当A[]={0}时,就是死循环了。
1 void swap(int &a,int &b){ 2 int tmp; 3 tmp=a; 4 a=b; 5 b=tmp; 6 } 7 void sortColors(int A[], int n) { 8 if(A==NULL||n<=0) 9 return; 10 int i,j,k; 11 i=0; 12 j=n-1; 13 k=0; 14 while(k<=j) 15 { 16 if(A[k]==2) 17 { 18 swap(A[k],A[j]); 19 j--; 20 } 21 if(A[k]==0) 22 { 23 swap(A[k],A[i]); 24 i++; 25 k++; 26 } 27 if(A[k]!=0&&A[k]!=2) 28 k++; 29 } 30 }
AC
明哥说,等于0的时候可以k++,等于2时不能k++
不理解