点击蓝字 关注我们
大家好,这一期我来给大家分享一个常见的排序算法:快速排序算法。
那么看完这篇文章之后,你可以了解到
1.什么是快速排序?
2.如何实现快速排序?
3.如何在O(n)的时间复杂度内查找一个无序数组的第K大元素
01
什么是快速排序
快速排序,我们习惯性把它称之为“快排”。
02
如何实现快速排序?
了解过快速排序算法的同学应该都知道,快速排序的切分思想可以用于计算某个位置的数值等问题。
切分思想如下
我们通过切分要使数组满足以下条件:
1. 对于某个 j,a[j] 已经排定
2. a[low] 到 a[j] 中的元素都不大于 a[j]
3. a[j+1] 到 a[high] 中所有元素都不小于 a[j]
如何实现切分
1. 先随机抽取一个数 a[low] 作为切分元素
2. 从数组左端开始向右扫描直到找到一个大于等于它的元素,再从数组的右端开始向左扫描直到找到一个小于等于它的元素。这两个元素显然没有排定,我们交换他们的位置,如此继续我们就可以保证 j 的左侧不会大于切分元素,j 的右侧不会小于切分元素。
3. 当两个指针相遇时,只需要将切分元素 a[low] 和左子数组最右侧元素 a[j] 交换然后返回 j 即可
代码如下
03
快排的应用
快速排序的核心思想就是分治和分区,那么我们可以利用分区的思想。来解决:在 O(n) 时间复杂度内求无序数组的第 K 大元素。
举个例子
无序数组:4,2,5,12,3
第 3 大元素就是 4
我们选择数组区间 A[0...n-1] 的最后一个元素作为切分元素 pivot,对数组进行原地分区,这样数组就分成了三个部分 A[0...p-1],A[p] ,A[p+1...n-1]
如果 p+1==K,那么A[p]就是要求解的元素;若 K>p+1 则说明第K大元素出现在 A[p+1…n-1] 区间内,我们再按照上面的思路在 A[p+1...n-1] 区间内查找;若 K
那么为什么时间复杂度是O(n)?
第一次分区查找,我们需要对大小为n的数组执行分区操作,需要遍历n个元素。第二次查找我们需要对 n/2 的数组进行分区操作,需要遍历 n/2 个元素;以此类推,分区遍历元素分别为 n,n/2,n/4,n/8,n/16......直到区间缩小为1
我们把每次分区遍历元素的个数加起来,就是:n+n/2+n/4+n/8+n/16+…+1。等比数列求和,最后为 2n-1。那么时间复杂度为 O(n)。
04
内容小结
1. 快速排序用的是分治思想,代码可以通过递归来实现,理解快排的重点在于递推公式与分区函数。
2. 快速排序算法最坏情况下的时间复杂度为 O(n^2),平均情况下时间复杂度为 O(nlogn)。尽管快排的时间复杂度退化到 O(n^2) 的概率很小,我们仍应该通过选择合理的 pivot 来避免这种情况。
3. 点击下方原文查看github链接。
— END —
撰稿:赵英杰
图文编辑:田依可