Sort Colors
Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue.
Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.
Note:
You are not suppose to use the library's sort function for this problem.
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.
Could you come up with an one-pass algorithm using only constant space?
不看題目限制,大家都能想到的就是計數排序了。需要掃兩遍,一遍數,一遍賦值。
【最簡單:計數排序】
class Solution { public: void sortColors(int A[], int n) { int i = 0; int j = 0; int k = 0; for(int p = 0; p < n; p ++) { if(A[p] == 0) { i ++; } else if(A[p] == 1) { j ++; } else k ++; } for(int p = 0; p < n; p ++) { if(p < i) A[p] = 0; else if(p >= i && p < i + j) A[p] = 1; else A[p] = 2; } } };
如果只能掃一遍,很容易想到的就是左邊存放0和1,右邊存放2.兩邊往中間靠。
設置兩個index,left記錄第一個1的位置,left左邊為0,right記錄第一個非2的位置,right右邊為2.
然后使用i從頭到尾掃一遍,直到與right相遇。
i遇到0就換到左邊去,遇到2就換到右邊去,遇到1就跳過。
需要注意的是:由於left記錄第一個1的位置,因此A[left]與A[i]交換后,A[left]為0,A[i]為1,因此i++;
而right記錄第一個非2的位置,可能為0或1,因此A[right]與A[i]交換后,A[right]為2,A[i]為0或1,i不能前進,要后續判斷。
由此該數組分為4段:[0,left)-->0; [left,i)-->1; [i,right]-->亂序; (right,n-1]-->2
0 0 0 1 1 1 2 1 0 2 1 2 2 2
^ ^ ^
left i right
【最直接:partition】
class Solution { public: void sortColors(int A[], int n) { int left = 0; int right = n-1; int i = 0; while(i <= right) { if(A[i] == 0) { swap(A[left], A[i]); left ++; i ++; } else if(A[i] == 1) { i ++; } else { swap(A[i], A[right]); right --; } } } };
這是網上看到一種漂亮的做法,膜拜。
【最直觀:平移插入】
class Solution { public: void sortColors(int A[], int n) { int i = -1; int j = -1; int k = -1; for(int p = 0; p < n; p ++) { //根據第i個數字,挪動0~i-1串。 if(A[p] == 0) { A[++k] = 2; //2往后挪 A[++j] = 1; //1往后挪 A[++i] = 0; //0往后挪 } else if(A[p] == 1) { A[++k] = 2; A[++j] = 1; } else A[++k] = 2; } } };