算法思路:
- 递归找pivot,然后按小于pivot和大于等于pivot分成两组。每轮递归,pivot肯定在正确(最终)位置上
- partition方法类似于Leetcode75的sort colors一样用两个指针i和noSmallerIdx。i是循环指针,而
noSmallerIdx是第二组大于等于pivot的首元素,或者理解为比pivot小的元素(指针i指着)将要被交换
的位置(比pivot大的元素)=比pivot小的元素的最后一个+1. - 循环结束后,将pivot交换到正确的位置上。

i指向4,因为4小于pivot,所以要换到前面去,跟6置换,noSmallerIdx向后移。
应用:
- 排序
- 快速选择quick select
- partition,如Leetcode 75
Python代码:
1 | def quick_sort(self, nums: List[int]): |
算法分析:
时间复杂度为O(nlogn),空间复杂度O(1)。
Quick Select
选择第k小的数(下标从0开始)
注意事项:
- left > right不再是等于,因为几个数相等的情况,排序的时候不用再移动,但第k小里面需要继续递归。
- binary select是单边递归,而不是双边。要判断pivot是否等于k。
- 递归调用仍用k,而不是跟pivot_pos相关,因为k是下标位置
- partition中range用[start, end)而不是len
Python代码:
1 | def quick_select(self, nums: List[int], k: int) -> int: |
算法分析:
时间复杂度为O(n),空间复杂度O(1)。
Partition
用于原位排序,将相应的元素放入该放的位置直到不满足条件为止
注意事项:
- i不一定会移动,放在else里面
1 | def sort(self, nums: List[int]) -> int: |
上述算法的问题不能有效处理两种情况:
- 有序数组[1, 2, 3, 4]
- 单一数组[2, 2, 2, 2]
第一种情况递归为
[123]
[12]
[1]
只会递归左半,不会递归右半
第二种情况
[2222]
[222]
[22]
[2]
只会递归右半,不会递归左半
这两种情况都是O(n^2)
解决第一个问题用randomize pivot的方法
解决第二个问题用three-way partition的方法,类似于75 Sort colors将区间从两个变成3个: 小于pivot, 等于pivot,大于pivot,这样对于单一值数组,左半和右半就不会递归了
Python代码:
1 | def sortArray(self, nums: List[int]) -> List[int]: |
Java代码:
1 | public void sort(int[] arr) { |


