题目:n个数中,求最小的前k个数。
这道题在各个地方都看到过,在国内出现的频率也非常高。
解法:
1. brute force。 O(k*n)复杂度;
2. sort。O(k+n*lgn)复杂度;
3. 最大堆。每次替代的是大小为k的最大堆的最大值。O(k+(n-k)lgk)复杂度。
4. 最小堆。和sort类似,只是建堆后只求前k次。O(n+k*lgn)复杂度。在网上看到一个优化,就是pop出第k小的数(堆顶)的时候,最多只需要调整k-1层(不需要调到堆底)。所以可以优化到O(n+k^2)。当然这个建堆需要O(n)的空间复杂度,所以还是弱一点。
5. 类quick sort。求第k小的数。pivot用的是“五分化中项的中项”。因为每次划分之后,只需要考虑其中一部分的数,证明过程类似于堆排序建堆用了O(n)的开销证明。开销也在O(n)。
“五分化中项的中项”划分法:
- 将输入数组的N个元素划分为[n/5]组,最后一个组剩下的n mod5组成;
- 寻找每一组的中位数:首先对每组的元素进行插入排序,排序后选出一些中位数;这样可以确保,对于这一些中位数,大于它们的数的个数约等于小于它们的数的个数;
- 对找出的[n/5]个中位数,继续递归找到其中位数,作为最终的pivot;
- 基于pivot进行partition划分;
时间: 2024-10-04 21:47:24