快速排序简介
快速排序是一种高效的排序算法,平均时间复杂度为 O(nlogn),最坏情况下为 O(n^2)。它通过选定一个基准(pivot),将数组划分为小于和大于基准的部分,然后递归地对这两部分排序。其优势在于分治策略和对大部分情况下的高效性能。
实现方法概览
- 基础快速排序:最右元素为基准。
- 双指针法快速排序:双指针交替缩进。
- 快速选择(Quickselect) :用于查找数组第
k大元素。
注:图片来自Krahets
原链接🔗
在这篇博客中,我们将详细探讨快速排序的三种常用实现方法,包括基础递归实现、双指针分区方法以及随机基准的快速选择(Quickselect)算法。这些方法的核心思想是分治法,即通过选取基准将数组分为小于和大于基准的两个部分,再对这两部分递归进行排序。我们将通过每种实现的代码及详细说明,帮助您更好地理解快速排序的工作原理。
方法一:基础快速排序
def quick_sort(arr, left, right):
if left < right:
pivot_index = partition(arr, left, right)
quick_sort(arr, left, pivot_index - 1)
quick_sort(arr, pivot_index + 1, right)
def partition(arr, left, right):
pivot = arr[right] # 选择最右边元素为基准
i = left - 1 # 初始化 i 为小于基准的边界
for j in range(left, right):
if arr[j] < pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i] # 将小于基准的元素移到左侧
arr[i + 1], arr[right] = arr[right], arr[i + 1] # 基准放到正确位置
return i + 1 # 返回基准的索引
详细步骤
- 选择基准:将最右侧元素选为基准。
- 分区:通过
i指针将数组划分为小于和大于基准的部分,j遍历数组,将小于基准的元素移到左边。 - 递归:递归对左右子数组排序,直到所有子数组有序。
方法二:双指针法快速排序
def quick_sort(arr, left, right):
if left < right:
pivot_index = partition(arr, left, right)
quick_sort(arr, left, pivot_index - 1)
quick_sort(arr, pivot_index + 1, right)
def partition(arr, left, right):
pivot = arr[left] # 选择最左边元素为基准
l, r = left, right
while l < r:
while l < r and arr[r] >= pivot: # 从右找到小于基准的元素
r -= 1
arr[l] = arr[r]
while l < r and arr[l] <= pivot: # 从左找到大于基准的元素
l += 1
arr[r] = arr[l]
arr[l] = pivot # 基准放到正确位置
return l # 返回基准的索引
详细步骤
- 选择基准:选择数组的最左侧元素。
- 分区:通过双指针移动,
l指向大于基准的第一个元素,r指向小于基准的第一个元素,然后交换二者。 - 递归:递归对左右子数组进行排序。
方法三:快速选择(Quickselect)
快速选择是一种基于快速排序的算法,用于查找数组的第 k 大元素。其原理类似于快速排序,通过基准分区,但只递归处理包含第 k 大元素的那部分子数组。
import random
class Solution:
def findKthLargest(self, nums, k):
def quick_select(nums, k):
pivot = random.choice(nums) # 随机选择基准
big, equal, small = [], [], []
for num in nums:
if num > pivot:
big.append(num)
elif num < pivot:
small.append(num)
else:
equal.append(num)
if k <= len(big):
return quick_select(big, k)
if len(nums) - len(small) < k:
return quick_select(small, k - len(nums) + len(small))
return pivot
return quick_select(nums, k)
详细步骤
-
选择基准:随机选择一个基准元素。
-
分区:根据基准,将数组分为三部分:
big(大于基准)、equal(等于基准)、small(小于基准)。 -
递归:
- 若第
k大元素在big中,则递归查找big。 - 若第
k大元素在small中,则递归查找small。 - 若在
equal中,直接返回基准值。
- 若第