1. 程式人生 > >OJ - 75 對0,1,2進行排序(Sort Color)

OJ - 75 對0,1,2進行排序(Sort Color)

題目:給定一個數組,數組裡面的元素取值為:[0, 2],把這個陣列排序。

1.第一種做法:計數排序,因為數組裡面的元素都是正數,可以直接索引到,所以我們直接可以開一個size為3的陣列,用來儲存0,1,2的個數。最後再直接覆寫原來的陣列即可。

void sortColors(vector<int>& nums) {
        vector<int> current(3, 0);
        int size = nums.size();
        for (int i = 0; i < size; ++i) {
            current[nums[i]]++;
        }
        int
start = 0, end = 0; for (int i = 0; i < 3; ++i) { end += current[i]; for (int j = start; j < end; ++j) { nums[j] = i; } start += current[i]; } }

這個演算法的時間複雜度為O(N),空間複雜度為O(max(nums))[考慮到如果輸入不止為0,1,2的時候],這個是計數排序的弊端。

我們最好弄一個只遍歷一遍,並且沒有額外空間的使用的演算法:
我們使用三個指標來幫助我們標記當前的元素:i代表遍歷陣列的指標,j代表下一個0元素該出現的地方,k表示下一個2元素該出現的地方。然後我們遍歷這個陣列:噹噹前的元素為0的時候,交換i和j指標的數。並且讓j自增,噹噹前元素為2的時候,交換i和k指標的數,並且讓k自減,i自減,i自減的目的是:不知道交換過來的數到底是幾,所以需要重新判斷。
為什麼1不用判斷:因為我們處理了0和2,放在中間的1自然就有序了,不用處理。所以我們可以有下面的程式碼:

void sortColors(vector<int>& nums) {
        int
k = nums.size() - 1; int j = 0; for (int i = 0; i <= k; i++) { if (nums[i] == 0) { swap(nums[i], nums[j++]); } else if (nums[i] == 2) { swap(nums[i--], nums[k--]); } } } void swap(int& a, int& b) { int c = b; b = a; a = c; }