Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 最大堆中的第k个最大元素_Algorithm_Data Structures_Heap_Pseudocode - Fatal编程技术网

Algorithm 最大堆中的第k个最大元素

Algorithm 最大堆中的第k个最大元素,algorithm,data-structures,heap,pseudocode,Algorithm,Data Structures,Heap,Pseudocode,我试图想出一些办法来解决以下问题: 给定一个表示为数组的最大堆,返回第k个最大元素而不修改堆。我被要求在线性时间内完成,但被告知可以在日志时间内完成 我想到了一个解决办法: 使用第二个max堆,并在其中填充k或k+1值(宽度优先遍历原始堆),然后弹出k个元素并获得所需的元素。我想这应该是O(N+logN)=O(N) 是否有更好的解决方案,也许在O(logN)时间内?据我所知,解决这个问题没有简单的算法。我所知道的最好的算法是弗雷德里克森的,这并不容易。您可以查看它在时间O(k)内运行的论文,这被

我试图想出一些办法来解决以下问题:

给定一个表示为数组的最大堆,返回第k个最大元素而不修改堆。我被要求在线性时间内完成,但被告知可以在日志时间内完成

我想到了一个解决办法:

使用第二个max堆,并在其中填充k或k+1值(宽度优先遍历原始堆),然后弹出k个元素并获得所需的元素。我想这应该是O(N+logN)=O(N)


是否有更好的解决方案,也许在O(logN)时间内?

据我所知,解决这个问题没有简单的算法。我所知道的最好的算法是弗雷德里克森的,这并不容易。您可以查看它在时间O(k)内运行的论文,这被认为是可能的最佳时间,因此我怀疑不存在日志时间解决方案

如果我找到比这更好的算法,我一定会让你知道的

希望这有帮助

不,没有O(logn)时间算法,通过一个简单的细胞探针下限。假设k是2的幂(不丧失一般性),堆看起来像(minheap-incoming,因为它更容易标记,但没有真正的区别)


在最坏的情况下,我们必须读取整个排列,因为堆不存在强加的顺序关系,并且只要没有找到k,它就可以位于尚未检查的任何位置。这需要时间ω(k),与templatetypedef发布的(复杂!)算法相匹配。

最大堆可以有多种方式,更好的情况是完整排序数组,在另一种极端情况下,堆可以具有完全不对称的结构

这里可以看到:

在第一种情况下,第k个最长的元素位于第k个位置,您可以使用heap的数组表示在O(1)中进行计算。 但是,一般来说,您需要在(k,2k)元素之间进行检查,并对它们进行排序(或使用另一堆进行部分排序)。据我所知,是O(K·log(K))

算法是:

Input:
    Integer kth <- 8
    Heap heap <- {19,18,10,17,14,9,4,16,15,13,12}

BEGIN
    Heap positionHeap <- Heap with comparation: ((n0,n1)->compare(heap[n1], heap[n0]))

    Integer childPosition
    Integer candidatePosition <- 0
    Integer count <- 0
    positionHeap.push(candidate)
    WHILE (count < kth) DO
        candidatePosition <- positionHeap.pop();
        childPosition <- candidatePosition * 2 + 1
        IF (childPosition < size(heap)) THEN
            positionHeap.push(childPosition)
            childPosition <- childPosition + 1
            IF (childPosition < size(heap)) THEN
                positionHeap.push(childPosition)
            END-IF
        END-IF
        count <- count + 1
    END-WHILE
    print heap[candidate]
END-BEGIN
输入:

整数kth数组中的最大堆:
i处的元素大于2*i+1和2*i+2处的元素(
i
基于0)

您将需要另一个最大堆(
insert
pop
empty
),其中的元素对
(值,索引)
排序。伪代码(无边界检查):

输入:k
1.插入(在(0),0处)

2.(v,我)明白了,谢谢,但在这种情况下,我仍然认为你的算法是错误的,因为树的广度优先搜索不会正常工作?我想它应该会工作。我错误地使用了术语“搜索”,基本上我只是在搜索一个遍历,它存储一个级别的节点,然后继续下一个级别。我将编辑该术语以消除任何潜在的歧义。我认为斐波那契堆是实现摊销O(logn)解决方案的方法,但我喜欢这个问题。我要考虑一下…@Alstor我认为你的解决方案不对,因为第k个最大元素不需要在树的第k级。@Alstor如果你只是要遍历树并使用堆栈,那么为什么要使用第二个最大堆,因为遍历不会修改堆?标题说最大堆中的第k个最大元素(不是任意数组)。因此,不存在min heap到来的问题。您概述的最坏情况不适用,因为它是最大堆,所以父节点总是高于其子节点。@Kishore我的回答是,在最坏情况下,堆结构不会施加太多的结构。您能为语句“通常,您需要在(k,2k)元素之间进行检查”提供站点引用吗?例如,在图像中,第七大元素9位于索引1处,而在图像中,第四大元素12位于索引14处。所以我猜这个说法是错误的。@anir在你的第一个例子中,你怎么知道第七大元素是什么?要确定哪一个是第七大元素,您必须评估9个元素。所以我认为,通过“检查(k,2k)元素之间的关系,并对它们进行排序”,您的意思是对堆数组索引k和2k之间的元素进行排序。现在我觉得,这不是你想说的,对吧?我说这是错误的,因为在第一个例子中,9是第七大元素,但出现在索引1处。因此,我们无法通过对索引7和14之间的元素进行排序(然后从中选择最小的元素),将9确定为第七大元素。类似地,在第二个示例中,第四大元素12出现在索引14处。因此,我们无法通过对指数4和8之间的元素进行排序来确定12为第四大元素。(续…(续…)可能是本可以避免混淆的例子。现在我觉得您谈论的是与这些答案中解释的相同的过程:,而不是直接在索引k和2k之间对堆数组元素进行排序(然后从排序输出中选择最小值),对吗?
Input:
    Integer kth <- 8
    Heap heap <- {19,18,10,17,14,9,4,16,15,13,12}

BEGIN
    Heap positionHeap <- Heap with comparation: ((n0,n1)->compare(heap[n1], heap[n0]))

    Integer childPosition
    Integer candidatePosition <- 0
    Integer count <- 0
    positionHeap.push(candidate)
    WHILE (count < kth) DO
        candidatePosition <- positionHeap.pop();
        childPosition <- candidatePosition * 2 + 1
        IF (childPosition < size(heap)) THEN
            positionHeap.push(childPosition)
            childPosition <- childPosition + 1
            IF (childPosition < size(heap)) THEN
                positionHeap.push(childPosition)
            END-IF
        END-IF
        count <- count + 1
    END-WHILE
    print heap[candidate]
END-BEGIN
input: k
1. insert (at(0), 0)
2. (v, i) <- pop and k <- k - 1
3. if k == 0 return v
4. insert (at(2*i+1), 2*i+1) and insert (at(2*+2), 2*+2)
5. goto 2