Algorithm 如何确定堆的第k个最大元素是否大于x

Algorithm 如何确定堆的第k个最大元素是否大于x,algorithm,complexity-theory,binary-heap,Algorithm,Complexity Theory,Binary Heap,考虑一个包含n的二进制堆 数字(根存储的数字最大)。你得到了一份工作 正整数kminHeap.size()){ 返回false; } if(minHeap.getByIndex(index)=k){ 返回true; } 退货检查(2*索引)|| 检查(2*索引+1); } 返回false; } 公共静态void main(字符串[]args){ ksmallet2ks=newksmallet2(“src/main/resources/minheap.txt”,18,5); System.out.

考虑一个包含n的二进制堆 数字(根存储的数字最大)。你得到了一份工作 正整数k算法必须花费O(k)时间。您可以使用O(k)额外存储

简单的dfs即可完成此任务。我们把计数器设为零。从根开始,在每次迭代中检查当前节点的值;如果大于x,则增加计数器并继续对其中一个子节点执行算法。如果计数器大于等于k,或者没有节点可供检查,则该算法终止。运行时间是O(k),因为最多迭代k个节点,每个迭代都在O(1)中

伪代码如下所示

    void CheckNode(Node node,int k, int x, ref int counter)
    {
        if (node.value > x)
        {
            counter++;
            if (counter >= k)
                return;

            CheckNode(node.Left, k, x, ref counter);
            CheckNode(node.Right,k, x, ref counter);
        }
    }
使用它:

        counter = 0;
        CheckNode(root,index,val,counter );
        if (counter >= index)
            return true;
        return false;
如果node.value 正如@Eric Mickelsen在评论中提到的,最坏情况下的运行时间正好是2k-1(k>0),如下所示

    void CheckNode(Node node,int k, int x, ref int counter)
    {
        if (node.value > x)
        {
            counter++;
            if (counter >= k)
                return;

            CheckNode(node.Left, k, x, ref counter);
            CheckNode(node.Right,k, x, ref counter);
        }
    }
使用大于x的值访问的节点数最多为 K使用小于x的值访问的每个节点都必须是 值大于x的已访问节点。但是,因为每个节点 除根目录外,必须有一个值大于x的父目录, 访问的值小于x的节点数最多必须为 ((k-1)*2)-(k-1)=k-1,因为(k-1)*2子级中的k-1具有值 大于x。这意味着我们访问大于x和x的k个节点 k-1小于x,即2k-1

公共类KSmallest2{
私有MinPQ-minHeap;
私人INTX;
私人INTK;
私有整数计数=0;
公共KSmallest2(字符串文件名,int x,int k){
这个.x=x;
这个。k=k;
minHeap=新的MinPQ();
试一试{
扫描仪输入=新扫描仪(新文件(文件名));
while(在.hasNext()中){
insert(in.nextInt());
}
}catch(filenotfounde异常){
e、 printStackTrace();
}
}
公共布尔检查(整数索引){
如果(索引>minHeap.size()){
返回false;
}
if(minHeap.getByIndex(index)=k){
返回true;
}
退货检查(2*索引)||
检查(2*索引+1);
}
返回false;
}
公共静态void main(字符串[]args){
ksmallet2ks=newksmallet2(“src/main/resources/minheap.txt”,18,5);
System.out.println(ks.minHeap);
系统输出打印LN(ks检查(1));
}

}

@Nikita Rybak,我没有找到第k个较大的元素,问题:“您必须确定堆的第k个最大元素是否大于x”,如果第2k个最大元素大于x,则确定第k个最大元素大于x。谁在乎kth最大元素?只关心x是否大于那个值。@Nikita Rybak-它并没有声明哪一个是第k大的,只有多少元素大于x。堆在某种意义上排序,如果它大于x本身,则只需要考虑它的子。这个算法是正确的。@Saeed好的,显然我不识字。这确实是正确的。干得好。@Nikita:别自责。标题完全是误导性的。@Eric Mickelsen,关于“确定堆的第K个最大元素是否大于x”的问题没有找到第K个最大元素,因此如果您找到了大于
x
的K个项目,就没有必要找到第K个最大元素,如果它刚好小于第K个最大元素,您知道所有父元素(从根元素到第K个最大元素的路径中)都大于此值,因此树到第K个最大元素的最大高度为
K
,并且您只需检查父元素是否大于x(最多K次)所以,在到达第k个最大元素之前,您没有检查超过3*k个节点。-1:这是一个有趣的问题,但这是发布问题的错误方式。请不要在这里逐字复制作业。