給定一個包含紅,白,藍且長度為 n 的數組,將數組元素進行分類使相同顏色的元素相鄰,并按照紅、白、藍的順序進行排序。我們可以使用整數 0,1 和 2 分別代表紅,白,藍。
注意事項
不能使用代碼庫中的排序函數來解決這個問題。排序需要在原數組中進行。
樣例
給你數組 [1, 0, 1, 2], 需要將該數組原地排序為 [0, 1, 1, 2]。
挑戰
一個相當直接的解決方案是使用計數排序掃描 2 遍的算法。首先,迭代數組計算 0,1,2 出現的次數,然后依次用 0,1,2 出現的次數去覆蓋數組。你否能想出一個僅使用常數級額外空間復雜度且只掃描遍歷一遍數組的算法?
代碼
public class Solution {
/*
* @param nums: A list of integer which is 0, 1 or 2
* @return: nothing
*/
public void sortColors(int[] nums) {
if (nums == null || nums.length == 0) {
return;
}
// i 從第一個數開始遍歷,代表當前數值點
// pl 指向第一個不是 0 的數,pl 的左邊應該全是 0
// pr 指向第一個不是 2 的數,pr 的右邊應該全是 2
int pl = 0;
int pr = nums.length - 1;
int i = 0;
// pr 指向的不是 2 所以要遍歷 pr 位置,此處寫 <=
while (i <= pr) {
if (nums[i] == 0) {
// 因為左邊點只有是 1 的時候直接跳過,2 的時候會處理,所以在 0 和 1 位置交換后直接進行 i++
swap(pl, i, nums);
i++;
pl++;
} else if (nums[i] == 1) {
i++;
} else {
/* 注意此處不能 i++, i 代表當前數值點
* nums[i] 和 nums[pr] 交換后,如果出現類似于 nums[i] =nums[pr] = 2
* 說明當前交換除了執行 pr--外對左邊值并未處理,應該針對當前值進行下一輪判斷操作
* 如果直接 i++,數組毫無疑問會出現所有和 pr 交換完的點都沒進行處理
*/
swap(pr, i, nums);
pr--;
}
}
}
private void swap(int m, int n, int[] nums) {
int temp = nums[m];
nums[m] = nums[n];
nums[n] = temp;
}
}