- 前言
- 一、数组中的第K大元素
- 二、建堆复杂度证明
- 三、快排/优先队列/堆排
- 总结
- 参考文献
堆排可以不用完全排序,再取第K大元素,但是选择排序也亦如此。
那么谁会运行的更快呐?建堆时,需要调整n/2次,每次最大深度为log2(n),第一直观印象就是建堆T(n) = O(nlgon),其实不然。
堆排取k大元素的时间 = 建堆时间 + 取k个元素的时间 = (O(n) - O(log2n) - 1) + O(klog2n) = O(n);
选择排序取k大元素的时间 = O(kn) = O(n).
因为(O(n) - O(log2n) - 1) + O(klog2n) 证明在第二部分代码前的注释中。 证明:以最多节点的满二叉树为例,树高为h, 设当前层为k,则该层有2^(k - 1)^个节点,每个节点需要调整h - k的深度。 所以,T(n) = 20 * (h - 1) + 21 * (h - 2) +…+2^(h - 2) * 1,显然是一个典型的差比数列,只需错位相减即可。 2T(n) = 21 * (h - 1) + 22 * (h - 2) +…+2^(h - 2)^ * 2 + 2^(h - 1) * 1, 两式差得T(n) = 2h - h - 1,注:h = log2(n),所以T(n) = O(n) - O(log2(n)) - 1 = O(logn) 注:计算复杂度,前提条件就是n足够大,如果n很小,就无复杂度可言,直接O(1) 1)堆排建堆的时间复杂度是O(n),不是O(nlogn). LeetCode 数组中的第K大元素package everyday.medium;
import java.util.PriorityQueue;
// 数组中第k个最大元素。
public class FindKthLargest {
// 选择排序 -- 虽然是O(n),但时间是Tn = kn,比起堆排,Tn = n - log(n+1) + klogn,还是要慢很多。
public int findKthLargest(int[] nums, int k) {
for (int i = 0; i < k; i++) {
// 选择
int max = nums[i], idx = i;
for (int j = i + 1; j < nums.length; j++) {
if (max < nums[j]) {
max = nums[j];
idx = j;
}
}
// swap
int t = nums[idx];
nums[idx] = nums[i];
nums[i] = t;
}
// 取值
return nums[k - 1];
}
// 堆排,熟练API,优先队列,整个大顶堆。
public int findKthLargest2(int[] nums, int k) {
// 大顶堆
PriorityQueue
总结
2)优先队列/堆排/选择排序。


![数组中的第K大元素[堆排 + 建堆的实际时间复杂度] 数组中的第K大元素[堆排 + 建堆的实际时间复杂度]](http://www.mshxw.com/aiimages/31/1000366.png)
