我使用最大堆来查找数组中的k个最大元素,如下所示:
1)我已经构建了给定数组的前k个元素(arr [0]到arr [k-1])的Min Heap MH。 O(k)的
2)对于每个元素,在第k个元素(arr [k]到arr [n-1])之后,将它与MH的根进行比较。
...... a)如果元素大于根,则将其设为root并为MH
调用heapify...... b)否则忽略它。
//步骤2是O((n-k))
3)最后,MH有k个最大元素,MH的根是第k个最大元素。
我已经搜索了网络,第二步的复杂性向我显示了O(nk)logk,我认为应该是(nk)* O(k)如果我们使用自下而上的方法构建堆。因为每一步我只是在找到更大的元素时替换root。并且堆积k个元素的数组的复杂性是O(k)
我错了请澄清。我只是需要知道我的想法是否正确?
我的方法如下:
private static void createMinHeap(int[] arr) {
for (int i = arr.length / 2; i >= 0; i--) {
restoreDown(arr, i);
}
}
private static void restoreDown(int[] arr, int i) {
int left = (2 * i) + 1;
int right = (2 * i) + 2;
int num = arr[i];
while (right <= arr.length) {
if (num <= arr[right] && num <= arr[left]) {
arr[i] = num;
return;
} else if (arr[right] < arr[left]) {
arr[i] = arr[right];
i = right;
} else {
arr[i] = arr[left];
i = left;
}
left = (2 * i) + 1;
right = (2 * i) + 2;
}
if (left == arr.length - 1 && arr[left] < num) {
arr[i] = arr[left];
i = left;
}
arr[i] = num;
}
答案 0 :(得分:2)
您的推理几乎是正确的,但是对于大小为k
的堆,heapify操作需要O(log k)
。因此,总复杂度为O(n log k)
。为什么?在最坏的情况下,您应该为每个n-k
个剩余元素执行heapify。由于k
已修复且n
可以是任意大,因此O(n)
步,最终会给O(n log k)
。
另见:
答案 1 :(得分:-2)
Selection algorithm允许您在O(n)时间内找到第k个元素或数组中的k个最大元素。