標籤:else == lse cto 演算法 ati col 依次 空間
給定一個包含紅色、白色和藍色,一共 n 個元素的數組,原地對它們進行排序,使得相同顏色的元素相鄰,並按照紅色、白色、藍色順序排列。
此題中,我們使用整數 0、 1 和 2 分別表示紅色、白色和藍色。
注意:
不能使用程式碼程式庫中的排序函數來解決這道題。
樣本:
輸入: [2,0,2,1,1,0]輸出: [0,0,1,1,2,2]
進階:
- 一個直觀的解決方案是使用計數排序的兩趟掃描演算法。
首先,迭代計算出0、1 和 2 元素的個數,然後按照0、1、2的排序,重寫當前數組。
- 你能想出一個僅使用常數空間的一趟掃描演算法嗎?
Partition
將列表元素分為三類:等於一的,大於一的,小於一的。可以用三路partition實現。
在介紹三路partition前,先複習一下經典的二路partition實現。如類似演算法導論上的版本:
int partition(vector<int>&arr, int low, int high){ int pivot = arr[low];//選第一個元素作為樞紐元 int location = low;//location指向比pivot小的元素段的尾部 for (int i = low + 1; i <= high; i++)//比樞紐元小的元素依次放在前半部分 if (arr[i] <= pivot) swap(arr[i], arr[++location]); swap(arr[low], arr[location]); return location;}
partition返回的下標,下標及下標左邊是全部<=pivot的。如果是想要全部<pivot,可以把if中的小於等號改為小於符號。
第二種寫法是雙指標的,也是從數組左邊取pivot:
int mypartition(vector<int>&arr, int low, int high){ int pivot = arr[low];//選第一個元素作為樞紐元 while(low < high) { while(low < high && arr[high] >= pivot)high--; arr[low] = arr[high];//從後面開始找到第一個小於pivot的元素,放到low位置 while(low < high && arr[low] <= pivot)low++; arr[high] = arr[low];//從前面開始找到第一個大於pivot的元素,放到high位置 } arr[low] = pivot;//最後樞紐元放到low的位置 return low;}
對這個題,三路partition如下:
class Solution {public: void sortColors(vector<int> &nums) { int zero = -1; // [0...zero] == 0 int two = nums.size(); // [two...n-1] == 2 for( int i = 0 ; i < two ; ){ if( nums[i] == 1 ) i ++; else if ( nums[i] == 2 ) swap( nums[i] , nums[--two]); else{ // nums[i] == 0 assert( nums[i] == 0 ); swap( nums[++zero] , nums[i++] ); } } }};
LeetCode 75. 顏色分類