给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
注意:
不能使用代码库中的排序函数来解决这道题。
示例:
输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]
进阶:
一个直观的解决方案是使用计数排序的两趟扫描算法。
首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。
你能想出一个仅使用常数空间的一趟扫描算法吗?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sort-colors
普通递归快排:
class Solution:
def sortColors(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
def partition(nums,left,right): 分成左边<v,右边>v的形式,找到v真正的位置
v = nums[right]
while(left<right):
while(left<right and nums[left]<=v):#条件nums[left]<=v一直满足的话,直到left=right才出来
left+=1
nums[right]=nums[left]
while(left<right and nums[right]>=v):#条件nums[right]>=v一直满足的话,直到left=right才出来
right-=1
nums[left] = nums[right]
nums[left]=v
return left
def quicksort(array, left, right):
if left<right:
idx = partition(array, left, right)
quicksort(array, left, idx-1)
quicksort(array, idx+1, right)
left = 0
right = len(nums)-1
quicksort(nums,left,right)
太憨了,用示例走一遍流程感受一哈快排,写给寄几看
[2,0,2,1,1,0],left = 0,right = 5 进18行,满足left<right,20行进入partition函数
while①[2, 0, 2, 1, 1, 2] while②[2, 0, 2, 1, 1, 2] nums[left]=v[0, 0, 2, 1, 1, 2]
idx 0 21行left=0,idx-1=-1进递归不满足19行不执行。
22行idx+1=1,right=5进递归,满足left<right,20行进入partition函数
left = 1,right = 5 while①[0, 0, 2, 1, 1, 2] idx 5
idx 5 进21行,满足left<right,20行进入partition函数,left = 1,right = 4
while①[0, 0, 2, 1, 2, 2]while② [0, 0, 2, 1, 2, 2] nums[left]=v [0, 0, 1, 1, 2, 2] idx 2
idx 2 21行1,1不走,22行left = 3,right = 4 while①left走一步[0, 0, 1, 1, 2, 2] idx 4
idx 4 3,3不走,5,4不走
回到idx 5 进22行,6,5不走 idx0也走完了,全部走完
非递归快排:用栈装左右指针
class Solution:
def sortColors(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
def partition(nums,left,right):
v = nums[right]
while(left<right):
while(left<right and nums[left]<=v):#条件nums[left]<=v一直满足的话,直到left=right才出来
left+=1
nums[right]=nums[left]
while(left<right and nums[right]>=v):#条件nums[right]>=v一直满足的话,直到left=right才出来
right-=1
nums[left] = nums[right]
nums[left]=v
return left
def quicksort(array):
stack = [0, len(array)-1]
while stack:
print(stack)
left, right = stack[0], stack[1]
idx = partition(array,left,right)
print(idx)
if idx>stack[0] and left<idx-1:
stack.append(left)
stack.append(idx-1)
if idx<stack[1] and idx+1<right:
stack.append(idx+1)
stack.append(right)
stack.pop(0)
stack.pop(0)
return array
left = 0
right = len(nums)-1
quicksort(nums)
快排优化,不用right位置来左右分,而是随机取一个值来左右分,据说效率提高一半,改partition:
#快排优化--随机选取base点,解决对于近乎有序数组,选取base为最小/最大值造成的效率退化
import random
def partition(array, left, right):
mid = random.randint(left,right) #随机取一个位置
array[right], array[mid] = array[mid], array[right] #把这个位置跟最右边交换,其他一样
value = array[right]
while left<right:
while left<right and array[left]<=value:
left += 1
array[right] = array[left]
while left<right and array[right]>=value:
right -= 1
array[left] = array[right]
array[left] = value
return left