快速排序
快排是一种平均O(nlogn)时间复杂度的排序算法,最坏时间复杂度为O(n^2)。
基本思想
- 找一个分界点x(第一个数、中点、随机)
- 将数组分为两个部分,使得左边<=x,右边>=x
- 对左右部分递归进行下去,直到长度为1直接返回
划分区间的方法
- 借用额外数组(不推荐,有额外空间浪费)
- 遍历原数组,小于等于界限的的放左边,大于等于的放右边
- 双指针原地修改
- l,r指向数组的右两端,符合条件就不断向中间移动,两个都不符合就交换一下,继续判断
代码示例
func quickSort(q []int, l int, r int) {
if l < r {
// 双指针划分
mid, i, j := q[(l+r)/2], l-1, r+1
for i < j {
i++
for q[i] < mid {
i++
}
j--
for q[j] > mid {
j--
}
if i < j {
q[i], q[j] = q[j], q[i]
}
}
// 对左右部分递归
quickSort(q, l, j)
quickSort(q, j+1, r)
}
}
快排的非递归写法
可以使用一个队列,存储要递归计算的lr边界,这里使用bfs遍历。 当然也可以使用栈,就是dfs遍历,结果都一样。
快排的链表写法
链表操作的思路和数组差不多,分成三个部分:小于x,等于x大于x。然后将这三个部分拼接在一起即可
快排解决TopK问题
经常遇到一些题目让我们求第k大、第k小、前k大、前k小(不要求顺序)的场景。又要求时间复杂度为O(n),那么可以对快排进行化简:
- 只递归对我们有用的部分,答案不在的部分就无需递归下去了