繁体   English   中英

O(klogk)时间算法从二进制堆中找到第k个最小元素

[英]O(klogk) time algorithm to find kth smallest element from a binary heap

我们有一个n节点二进制堆,它包含n不同的项(根目录下的最小项)。 对于k<=n ,找到O(klogk)时间算法以从堆中选择kth最小元素。

O(klogn)显而易见,但无法找出O(klogk) 也许我们可以使用第二堆,不确定。

好吧,你的直觉是对的,我们需要额外的数据结构来实现O(klogk),因为如果我们只是在原始堆上执行操作,那么术语logn将保持在最终的复杂性中。

从目标复杂度O(klogk)猜测,我觉得创建和维护一个大小为k的堆来帮助我实现目标。 您可能已经意识到,以自上而下的方式构建一个大小为k的堆需要O(klogk),这真的让我想起了我们的目标。

以下是尝试获得O(klogk)的尝试(不一定优雅或高效):

  1. 我们创建一个新的min heap,将其root初始化为原始堆的根。

  2. 我们通过删除当前根并将当前根的两个子项插入原始堆来更新新的最小堆。 我们重复这个过程k次。

  3. 生成的堆将由k个节点组成,其根目录是原始堆中的第k个最小元素。

注意:新堆中的节点应该在原始堆中存储其对应节点的索引,而不是节点值本身。 在步骤2的每次迭代中,我们实际上在新堆中添加了一个节点的网络(一个删除,两个插入),其中k次迭代将导致我们的新堆大小为k。 在第i次迭代期间,要删除的节点是原始堆中的第i个最小元素。

时间复杂度:在每次迭代中,从一个元素中删除一个元素需要O(3logk)时间,并将两个元素插入到新堆中。 在k次迭代之后,它是O(3klogk)= O(klogk)。

希望这个解决方案能够激发你的灵感。

假设我们正在使用minheap,以便根节点始终小于其子节点。

Create a sorted list toVisit, which contains the nodes which we will traverse next. This is initially just the root node.
Create an array smallestNodes. Initially this is empty.
While length of smallestNodes < k:
    Remove the smallest Node from toVisit
    add that node to smallestNodes
    add that node's children to toVisit

完成后,第k个最小节点位于smallestNodes [k-1]中。

根据toVisit的实现,您可以在log(k)时间内插入并在恒定时间内删除(因为您只删除了最顶层的节点)。 这使得O(k * log(k))总计。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM