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.

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分別計數,然後對整個陣列重新賦值,可以達到想要的結果。方法很巧妙。但如果元素只是記錄的關鍵字的話,這樣做就不合適了。還是尋求更通用的排序方法比較好。

方案一:

這道題目也就三種數,我們可以用快排的partition的i,j都向後移的方法來進行,第一次以0為關鍵字, 凡是為0都挪到i位置,不是0的都挪到後面。對剩餘的部分再進行一次partition。這樣進行兩趟partition就能解決問題。

通過這道題又發現了新的觀點。partition的“i,j都向後移”方法中key是可以任意指定一個數據的,而不一定非要是陣列中的元素,也不一定非要是陣列的起始位置的元素。而partition的“前後指標”方法,是需要某一個元素變成起始位置的元素後再進行排序。

程式碼如下:

class Solution {
public:
    void sortColors(int A[], int n) {
        int mid = Partition(A,0,n-1,0);
        Partition(A,mid,n-1,1);
    }

    int Partition(int A[],int begin,int end,int key){
        int i,j;

        for(i = j = begin;j <= end;j++){
            if(A[j] == key){
                Swap(&A[i],&A[j]);
                i++;
            }
        }
        return i;
    }

    void Swap(int *a,int *b){
        int temp = *a;
        *a = *b;
        *b = temp;
    }
};


方案二:

可以利用三個指標的方法來求解。當i,j,k。k指向最後。

1、當j為1的時候,就j++,不進行交換

2、當j為0的時候,就和i處的元素交換,然後i++和j++。(這裡的j++是因為保證了j前面的元素要麼為0,要麼為1,如果加強條件i==j時不交換,更省一點點時間

3、當j為2的時候,就和k處的元素交換,然後k--,但j不變,重新判斷j處的新值(也可以判斷k處的值再交換,不過增添了麻煩,直接交換比較好)

class Solution{
public:
    void sortColors(int A[],int n){
        int i,j,k;
        i = j = 0;
        k = n-1;

        while(j<=k){
            if(A[j] == 0){
                if(i != j)
                    Swap(&A[i],&A[j]);
                i++;
                j++;
            }else if(A[j] == 1) //該加else就必須加,不能單獨形成else,不然這句j+1後,下句判斷就以新的j來判斷了
                j++;
            else{
                Swap(&A[j],&A[k]);
                k--;
            }
        }
    }

    void Swap(int *a,int *b){
        int temp = *a;
        *a = *b;
        *b = temp;
    }
};