这是一道非常经典的题,在实际中有非常广泛的应用。
在这里做出一些总结。
常见的几种方法
1. 直接排序
看到问题的直观想法就是排序,排完序取前k个便是top k。
有许多排序方法,如快排、堆排,平均复杂度为O(N * log2N)
不过实际上找出top k个数我们并不需要对后 N-K 个数进行排序,这部分排序是无用功,所以我们应当除去,可以参考第三种方法。
2. 分治法
将数据分为x份,如果某个数为top k 数之一的话,那么在某份子集数据中,也应当在top k 中
因此找出每个子集的top k,再将这 x 个 top k 进行归并得到最终的top k
3. 基于快排的分治法
考虑快速排序的过程,选定一个主元,每次扫描都可以得到比主元大的集合S1,和比该主元小的集合S2。
当|S1| < k时,S1中的元素必然在 top k中,接下来只需在集合 S2 中寻找 top (k - |S1|)个元素
当|S1| > k时,S2中的元素必然都不在 top k 中,因此下一步在集合 S1 中寻找 top k 元素即可。
当|S1| = k时,可结束递归
众所周知,在一些极端情况下,快排的效果不是很好。因此出现了基于快速排序划分思想的二分法(BFPRT算法)。该方法能够使得最坏的情况下仍然为线性时间。
大致过程为:给元素分为5个一组,对其排序