本章收录于专栏:一起来刷题,持续更新中……
更多精彩文章,欢迎大家关注我,一起学习,一起进步~
本章来谈一谈快速排序算法。快排算法是一种很重要的算法,也经常会在面试中遇到。快排的时间复杂度为O(NlogN),空间复杂度为O(logN)。我们要掌握的并非快排实现方法本身,而是快排的思想。在LeetCode上很多题的解题方法,都会用到快排的思想。快速排序分为基础快排和随机快排。本章着重介绍随机快的实现。
随机快排的大概思路,是在一组数中,随机选取一个数,记为X,然后从数组两头遍历,把数组中大于X的数放右边,小于X的数放左边,等于X的数放中间,按照这个步骤(称为partition过程),就能把所有小于X的数移到左边,大于X的数移到右边,等于X的数移到中间。接着根据这个思路,再分别在小于X的数和大于X的数中,递归进行同样的操作,直到整体数组排序完成(sort过程)。
具体步骤如下图:
当partition结束后,我们分别将47左边的数组和右边的数组再重复一遍上述过程,注意这个子过程的pivot值不一定是47,因为每次partition我们的pivot取值为当前数组left和right位置的中间位置的数。不断重复上述过程,最终将整体数组排序完毕。
上代码:
def quickSort(self, nums):
if len(nums) == 1:
return nums
def partition(arr, left, right):
# 获取中间位置,这里使用>>符号其实有点炫技了,使用位操作的方法x>>1,比直接x//2要快
mid = left + ((right - left) >> 1)
target = arr[mid]
# 交换基准值和right位置的值
arr[mid], arr[right] = arr[right], arr[mid]
while left < right:
# 左边只判断是否小于等于基准值
while left < right and arr[left] <= target:
left += 1
arr[right] = arr[left]
# 右边只判断是否大于等于基准值
while left < right and arr[right] >= target:
right -= 1
arr[left] = arr[right]
# 最后需要将基准值放回到数组中left和right相遇的位置
arr[left] = target
return left
# 递归过程
def sort(arr, left, right):
if left >= right:
return
pivot = partition(arr, left, right)
# 易错写成sort(arr, left, pivot),之所以不能取到pivot,是因为在上一轮partition后,pivot位置的值已经排序完毕,不能再参与partition了;
sort(arr, left, pivot - 1) # 先排左边
sort(arr, pivot + 1, right) # 再排右边
return arr
return sort(nums, 0, len(nums) - 1)
要注意,快速排序在工程上(理论研究上,可能存在论文级别的稳定解决方法)是不稳定排序,即如果数组中存在相同元素,排序后,两个相同元素的相对位置会发生改变。