在最小堆中查找k个最小元素 - 最坏情况下的复杂性

时间:2017-12-19 17:13:53

标签: algorithm

我有一个带n个元素的最小堆,想要从这个堆中找到k个最小的数字。什么是最坏情况的复杂性?

这是我的方法:在stackoverflow的某个地方,我读到在最小堆中找到第i个最小数字的复杂性是O(i)。因此,如果我们想找到n-1最小的数字(n是没有意义的,因为它将是整个堆),总复杂度看起来像这样:

O(n-1)+O(n-2)+O(n-3)+…+O(2)+O(1)=O((1+n-1)*(n/2))=O(n^2)

这是对的吗?

2 个答案:

答案 0 :(得分:4)

不,时间比那更好。 O(k log(n))非常容易,O(k)如果你聪明的话。

从堆中查找和删除最小元素是O(log(n))。这很容易导致O(k log(n))时间。

但您正在考虑的结果是https://ac.els-cdn.com/S0890540183710308/1-s2.0-S0890540183710308-main.pdf?_tid=382a1cac-e4f7-11e7-8ac9-00000aab0f02&acdnat=1513713791_08f4df78a8821855e8ec788da063ea2f,它显示了如何及时找到k最小数字O(k)的大小。现在,您使用堆是二叉树的事实,并从根开始,并对您找到的小于最大值的每个数字进行递归搜索。然后使用k'最小号码的副本填写列表的其余部分。

在该搜索中,您最终会看到最多这个尺寸的所有k,对于其中一些,您会看到最多2个太大而无法打扰的父母,最多3k元素。这使得整个搜索O(k)

答案 1 :(得分:2)

我怀疑是否有可能及时识别出 O(k) 中的 k 最小元素。我之前看到的最好的是 O(k log k)算法,它还可以通过识别 k 最小元素来方便地解决您的问题。您可以在another answer on StackOverflowQuora上阅读详细信息。

基本思想是操纵辅助堆。最初,此辅助堆仅包含原始堆的根。在每个步骤中,算法都会删除辅助堆的min,并将其两个原始子项(即其子项从原始堆)插入到辅助堆中。

这个算法有一个很好的属性,在步骤 i ,它从辅助堆中删除的元素是整个 i 最小的元素。因此,在 k 步骤之后,已从辅助堆中删除的项集恰好是 k 最小元素。该算法是 O(k log k)因为 O(k)删除/插入到二级堆中,其大小上限为 O(k )

编辑:我的立场得到了纠正! btilly的回答使用this paper的结果在 O(k)中提供了解决方案。