题目描述:给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
注意:
不能使用代码库中的排序函数来解决这道题。
示例:
输入: [2,0,2,1,1,0] 输出: [0,0,1,1,2,2]进阶:
- 一个直观的解决方案是使用计数排序的两趟扫描算法。
首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。- 你能想出一个仅使用常数空间的一趟扫描算法吗?
解法1。必须原地更改数组,新建数组不行,输出不改变,按照进阶1的思路如下
class Solution(object):
def sortColors(self, nums):
"""
:type nums: List[int]
:rtype: void Do not return anything, modify nums in-place instead.
"""
if not nums:
return
cnt = [0]*3
for i in nums:
cnt[i] += 1
index = 0
for i in range(3):
for j in range(cnt[i]):
nums[index] = i
index += 1
解法2。按照进阶2的要求只遍历一遍数组,还好这道题只有3个值,所以相当于我们要把0搬到数组最前面,2搬到数组最后面,1若在中间就维持不变。用左右双指针,左指针存放0,右指针存放2,遇到1跳过。
class Solution(object):
def sortColors(self, nums):
"""
:type nums: List[int]
:rtype: void Do not return anything, modify nums in-place instead.
"""
if not nums:
return
l = 0
r = len(nums)-1
i = 0
while i <= r: # 注意这个地方用while不用for,for中i是自加,但i的值在循环体改变了,比较模糊
if nums[i] == 0:
tmp = nums[i]
nums[i] = nums[l]
nums[l] = tmp
l += 1
elif nums[i] == 2:
tmp = nums[i]
nums[i] = nums[r]
nums[r] = tmp
r -= 1
i -= 1
i += 1
解法3。同样只遍历1遍数组,k的作用是记录截止目前遍历过的数字个数,j记录的是0和1的个数,i记录的是0的个数,所相当于截至i全是0,然后剩下截至j全是1,然后再剩下截至k全是2,如是
class Solution(object):
def sortColors(self, nums):
"""
:type nums: List[int]
:rtype: void Do not return anything, modify nums in-place instead.
"""
if not nums:
return
i, j, k = -1, -1, -1
for n in nums:
if n == 0:
i += 1
j += 1
k += 1
nums[k] = 2
nums[j] = 1
nums[i] = 0
elif n == 1:
j += 1
k += 1
nums[k] = 2
nums[j] = 1
elif n == 2:
k += 1
nums[k] = 2