1. 程式人生 > >【LeetCode】Sort Colors 解題報告

【LeetCode】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.
click to show follow up.
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?

題意就是對一個包含0,1,2三種數字的陣列重新排序,使得排好序的陣列前一段都是0,中間一段都是1,最後一段都是2。

【掃描兩遍的計數排序】

public class Solution {
    public void sortColors(int[] A) {
        int i, r, w, b;
        r = w = b = 0;
        for (i = 0; i < A.length; i++) {
            if (A[i] == 0) r++;
            else  if (A[i] == 1) w++;
            else b++;
        }
        for (i = 0; i < A.length; i++) {
            if (i < r) A[i] = 0;
            else if (i < r + w) A[i] = 1;
            else A[i] = 2;
        }
    }
}

【掃描一遍,雙向遍歷】

從陣列兩端向中間遍歷,前面放0,後面放2,。把前面出現的2放到後面,後面出現的0放到前面,這樣中間剩下的就是1。

用i, j兩個指標遍歷陣列,r, b兩個變數記錄當前出現0和2的個數,也即放0和2的位置指標。

public class Solution {
    public void swap(int[] A, int a, int b) {
		int tmp = A[a];
		A[a] = A[b];
		A[b] = tmp;
	}
	
    public void sortColors(int[] A) {
        int len = A.length;
        int i, j, r, w, b;
        i = 0;
        j = len - 1;
        r = b = 0;
        while (i <= j) {
            if (A[i] == 0) {
                swap(A, i, r);
                i++;
                r++;
                continue;
            }
            if (A[j] == 2) {
                swap(A, j, len-1-b);
                j--;
                b++;
                continue;
            }
            if (A[j] == 0) {
                swap(A, i, j);
                continue;
            }
            if (A[i] == 2) {
                swap(A, i, j);
                continue;
            }
            //如果上述任何情況都不滿足,那麼只有下面一種可能
            //if (A[i] == 1 && A[j] == 1) {
                i++;
                j--;
            //}
        }
    }
}

【掃描一遍,單向遍歷】

後來發現,從一個方向遍歷更簡單,因為雙向遍歷兩個指標容易搞混,一個指標邏輯更清楚。

public class Solution {
    public void swap(int[] A, int a, int b) {
		int tmp = A[a];
		A[a] = A[b];
		A[b] = tmp;
	}
	
    public void sortColors(int[] A) {
        int len = A.length;
        int i, r = 0, b = 0;
        for (i = 0; i < len-b; i++) {
            if (A[i] == 0) {
                swap(A, i, r);
                r++;
            } else if (A[i] == 2) {
                swap(A, i, len-1-b);
                b++;
                i--; //後面交換過來的元素也要進行判斷
            } 
        }
    }
}