1. 程式人生 > 實用技巧 >leetcode hot 100 - 75. 顏色分類

leetcode hot 100 - 75. 顏色分類

75. 顏色分類

題目描述

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

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

注意:

不能使用程式碼庫中的排序函式來解決這道題。

示例:

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

進階:

一個直觀的解決方案是使用計數排序的兩趟掃描演算法。
首先,迭代計算出0、1 和 2 元素的個數,然後按照0、1、2的排序,重寫當前陣列。
你能想出一個僅使用常數空間的一趟掃描演算法嗎?

思路一:不借助計數排序,但是需要兩次遍歷

思路和交換0很像,也是使用一個下標指向下個0應該存放的位置,另一個指標碰到0後把這個0放到正確的位置即可,但是這裡有3個數,分別是0, 1, 2, 所以應該遍歷兩遍,第一遍把所有0都放到最前面,第二遍把所有2放在最後面

 1 class Solution {
 2     public void sortColors(int[] nums) {
 3         int len = nums.length;
 4         int next = 0;
 5         // 把所有的0移到最前面
 6         for(int i = 0; i < len; i++){
 7             if(nums[i] == 0){
 8                 int temp = nums[next];
 9                 nums[next++] = nums[i];
10 nums[i] = temp; 11 } 12 } 13 14 // 把所有的2移到最後面 15 next = len - 1; 16 for(int i = len - 1; i >= 0; i--){ 17 if(nums[i] == 2){ 18 int temp = nums[next]; 19 nums[next--] = nums[i]; 20 nums[i] = temp;
21 } 22 } 23 } 24 }
leetcode 執行用時:0 ms > 100.00%, 記憶體消耗:37.3 MB > 54.12%

複雜度分析:

時間複雜度:分別正序和倒序遍歷了一次陣列,所以時間複雜度為O(2n) 空間複雜度:O(1)

思路二:雙指標 + 一次遍歷

其實就是思路一的一個改進版

分別使用一個指標 p0 指向下個0的應該放置的位置,使用一個p2 指向下個 2 應該放置的位置。另一個指標 i 從前往後掃描,碰到 0 就和 p0所指的元素進行交換,然後p0 指標後移,碰到 2 就和 p2 所指元素進行交換,p2--, 但是這時 i 不能前移,因為不能確定nums[i]和 nums[p2]進行交換後,如果是0的話需要和nums[p0]交換,所以需要下輪繼續判斷nums[i]

 1 class Solution {
 2     public void sortColors(int[] nums) {
 3         int len = nums.length;
 4         
 5         int p0 = 0, p2 = len - 1;
 6         for(int i = 0; i <= p2; i++){
 7             if(nums[i] == 2){
 8                 // 因為不能確定nums[p2]是什麼,如果是0的話需要和nums[p0]交換,所以需要下輪繼續判斷nums[i]
 9                 nums[i--] = nums[p2];   
10                 nums[p2--] = 2;
11             }else if(nums[i] == 0){
12                 nums[i] = nums[p0];
13                 nums[p0++] = 0;
14             }
15         }
16     }
17 }

leetcode 執行用時:0 ms > 100.00%, 記憶體消耗:37.3 MB > 64.88%

複雜度分析:

時間複雜度:只遍歷了一遍陣列,所以時間複雜度為O(n)

空間複雜度:O(1)