題目描述
給定一個(gè)包含紅色、白色和藍(lán)色,一共 n 個(gè)元素的數(shù)組,原地對它們進(jìn)行排序,使得相同顏色的元素相鄰,并按照紅色、白色、藍(lán)色順序排列。
此題中,我們使用整數(shù) 0、 1 和 2 分別表示紅色、白色和藍(lán)色。
注意:
不能使用代碼庫中的排序函數(shù)來解決這道題。
示例
輸入: [2,0,2,1,1,0]
輸出: [0,0,1,1,2,2]
進(jìn)階
- 一個(gè)直觀的解決方案是使用計(jì)數(shù)排序的兩趟掃描算法。
首先,迭代計(jì)算出0、1 和 2 元素的個(gè)數(shù),然后按照0、1、2的排序,重寫當(dāng)前數(shù)組。 - 你能想出一個(gè)僅使用常數(shù)空間的一趟掃描算法嗎?
問題分析
數(shù)組中只有三種顏色,0居左,2居右。我們維持兩個(gè)左右指針p0,p1,當(dāng)前位置指針是cur,如果當(dāng)前數(shù)是0,則將p0位置的數(shù)與cur位置的數(shù)交換,p0與cur同時(shí)往右移動(dòng);如果當(dāng)前數(shù)是1,則cur繼續(xù)往右移動(dòng);這樣我們可以保證數(shù)組的前面部分始終是0,1有序的。如果當(dāng)前數(shù)是2,則將cur位置的數(shù)與p1位置的數(shù)交換,但此時(shí)只需p1左移一位,cur不動(dòng),因?yàn)闊o法保證交換后cur左邊的數(shù)依然是0,1有序的。總之,我們要保持cur左邊的數(shù)都始終都是(0,1)有序時(shí),才移動(dòng)cur,這樣才能逐步把0置換到左邊,2置換到右邊,剩下的1自然就在中間。
代碼
class Solution:
def swap(self, nums,a, b):
tmp = nums[b]
nums[b] = nums[a]
nums[a] = tmp
def sortColors(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
n = len(nums)
p0 = 0
p2 = n-1
cur = 0
while(cur<=p2):
if nums[cur] == 0:
self.swap(nums, p0, cur)
p0 +=1
cur +=1
if nums[cur] == 2:
self.swap(nums, p2, cur)
p2 -=1
# cur +=1
else:
cur += 1
對大小為N的數(shù)組進(jìn)行了一次遍歷,所以時(shí)間復(fù)雜度是O(N)。由于是原地置換,使用了常數(shù)空間,空間復(fù)雜度是O(1)。