題目描述:給定一個只包含 0、1、2 的整數陣列(代表紅、白、藍三色),請在不使用內建排序函式的情況下,就地(in-place)排序,使得相同顏色相鄰,且顏色順序為 0、1、2。
解題思路:
這道題又稱「荷蘭國旗問題」(Dutch National Flag Problem),由電腦科學家 Dijkstra 提出。樸素做法是計數排序(兩次遍歷),但最優解是一次遍歷、三指標法。
三指標(Three-Pointer)法:
維護三個指標:
low:下一個 0 應該放置的位置(初始為 0)mid:當前正在處理的元素(初始為 0)high:下一個 2 應該放置的位置(初始為 n-1)不變量(Loop Invariant):
[0, low) 全部是 0[low, mid) 全部是 1(high, n-1] 全部是 2[mid, high] 是尚未處理的區域處理邏輯(當 mid <= high 時):
nums[mid] == 0:與 nums[low] 交換,low++、mid++(因為 low 位置換來的必然是已處理過的 1)nums[mid] == 1:已在正確位置,mid++nums[mid] == 2:與 nums[high] 交換,high--(mid 不移動,因為換來的元素尚未檢查)整個過程只需一次掃描,每個元素最多被交換一次,效率極高。
時間複雜度:O(N) — 只需一次遍歷。mid 指標從左向右移動,high 指標從右向左移動,兩者相遇即停止,總操作次數不超過 N 次。
空間複雜度:O(1) — 只使用三個指標變數,就地排序,不需要額外的陣列空間。
1. Initialize low = 0, mid = 0, high = n - 1
2. While mid <= high:
a. If nums[mid] == 0:
- Swap nums[low] and nums[mid]
- Increment both low and mid
b. Else if nums[mid] == 1:
- Increment mid only
c. Else (nums[mid] == 2):
- Swap nums[mid] and nums[high]
- Decrement high only (do NOT increment mid)
3. Array is now sorted in-place計數排序 O(N),兩次遍歷:第一次遍歷統計 0、1、2 各自的數量,第二次遍歷依照計數重新填入陣列。這個方法需要兩次遍歷,但邏輯非常簡單,不容易出錯,在面試中作為「初步解法」說明後再優化到三指標法是常見策略。
STL sort O(N log N):直接呼叫 sort(nums.begin(), nums.end())。雖然正確,但題目明確要求不使用內建排序,且時間複雜度也不如線性方法優。此方法不符合題目要求,僅作為對比參考。