1. 程式人生 > >[LeetCode] 75.顏色分類

[LeetCode] 75.顏色分類

題目

顏色分類 給定一個包含紅色、白色和藍色,一共 n 個元素的陣列,原地對它們進行排序,使得相同顏色的元素相鄰,並按照紅色、白色、藍色順序排列。

此題中,我們使用整數 0、 1 和 2 分別表示紅色、白色和藍色。

輸入: [2,0,2,1,1,0] 輸出: [0,0,1,1,2,2]

要求:

  • 原地演算法
  • 複雜度O(n)
  • 不使用庫函式

思路

充分利用只有三個元素的特性。

方法一 —— 計數填充

掃兩遍,第一遍記錄下來三個元素的個數,第二遍填回nums。 這樣複雜度是O(2n)

方法二 —— 三指標法

使用三個指標i,j,k,分別指向0,1,2元素的末尾。

class Solution {
public:
void sortColors(vector<int>& nums) { int i=-1; int j=-1; int k=-1; for(int m=0;m<nums.size();m++) { if(nums[m]==0) { nums[++k]=2; nums[++j]=1; nums[++i]=0; } else
if(nums[m]==1) { nums[++k]=2; nums[++j]=1; } else if(nums[m]==2) { nums[++k]=2; } } } };

注意每個if裡的順序,當遇到0的時候,把三個指標都往前挪了一下,1會覆蓋掉2 , 0會覆蓋掉1。 不過這樣仍然存在重複的賦值操作,還可以進一步加速。

方法三——三路快排

思路:設兩個指標start,end,start指向0元素的末尾,end指向2元素的開頭。因為只有三個元素,start和end中間的都是1。以1為基準,大於1的放到隊末部分,小於1的放到隊首部分。 程式碼中遇到2就把2和nums[--end]

互換,把2扔到2元素的開頭。這時i指標不動,指向互換過來的元素,再次比較。

遇到0的話,把0和nums[++start]互換,把0扔到0元素隊尾。這時i指標+1,因為換過來的元素一定是0或1,因為i指標一直比start快,把2都換到了隊末。如果是0,則i和start一定是挨著的,這樣0和0互換位置沒有影響;如果是1,則當前序列一定是[...0s,1,..1,0i,..]這樣,互換之後,相當於把1序列中的第一個1和i互換。

遇到1的話,直接++就好。

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int start=-1;
        int end=nums.size();
        for(int i=0;i<end;)
        {
            if(nums[i]==2)
                swap(nums[--end],nums[i]);
            else if(nums[i]==1)
                i++;
            else if(nums[i]==0)
                swap(nums[++start],nums[i++]);
        }
    }
};