[LeetCode] 75.顏色分類
阿新 • • 發佈:2018-12-20
題目
顏色分類 給定一個包含紅色、白色和藍色,一共 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]
遇到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++]);
}
}
};