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

Algorithm 在最小堆中查找k个最小元素-最坏情况复杂性,algorithm,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) 这对吗?不,时间比那好多了O(k log(n))非常容易,如果你聪明的话,O(k) 从堆中查找和删除

我有一个包含
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)


这对吗?

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

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

但是,您正在考虑的结果是,它显示了如何在时间
O(k)
中找到
k
第个最小数的大小。现在使用堆是二叉树这一事实,从根开始,对找到的每个小于最大值的数字进行递归搜索。然后用
k
第四个最小数字的副本填写列表的其余部分

在该搜索中,您将查找最多为该大小的
k-1
,对于其中一些,您将查找最多为2个太大而无法处理的孩子,最多为
3k-3
元素。这使得整个算法
O(k)


那个链接因为bitrot而失效。希望能持续更长时间。

我怀疑是否有可能在时间O(k)内识别出第k个最小元素。我以前见过的最好的算法是O(k logk)算法,它还可以通过识别k个最小元素方便地解决您的问题。您可以在中或上阅读详细信息

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

这个算法有一个很好的特性,在第一步,它从二级堆中删除的元素是第i个最小的元素。因此,经过k个步骤后,从二级堆中删除的项集正好是k个最小的元素。这个算法是O(k log k),因为有O(k)个删除/插入到二级堆中,二级堆的大小上限为O(k)



编辑:我站起来更正!btilly的答案提供了一个O(k)的解决方案,使用的结果来自。

不可否认地认为,在最小堆中查找第k个最小元素的O(k)时间算法是一个真正需要实现的非常棘手的算法@灰胡子的措辞调整了。@greybeard哎呀,我指的是孩子。你链接的O(k log k)算法对我来说是新的,看起来非常实用——实现起来很简单,可能比Frederickson的最优O(k)时间算法快得多。