查找min-heap是否包含比查询更小的元素

时间:2016-01-29 02:20:29

标签: algorithm heap time-complexity

我长时间一直在摸不着头脑。我需要找到一个O(k)算法来查找min-heap是否比查询k具有q个更小的元素。

我尝试过这样的递归算法:

count = 0;
def kSmaller(H, q, k){
   if (root(H) == Null or root(H) >= q ) return;
   else {count++;
         if (count == k) return true;
         kSmaller(LeftChild(root(H), q, k)
         kSmaller(RightChild(root(H), q, k)
    }
}

但是在经历了一些最小堆的例子后,我无法理解如何在O(k)时间内终止,而不是不必要地遍历每个元素。

任何人都可以帮我理解如何处理这个问题吗?也许最好不要使用递归并将解决方案弄平。

2 个答案:

答案 0 :(得分:2)

最小堆的排列方式是每个节点小于它的两个子树中的所有节点。因此,当您看到一个大于或等于q值的节点时,您会删除递归,因此您的代码将花费O(k)时间。您可以绘制一些示例并查看。如果Min堆的p节点小于q,那么你只需要min(p,k)时间,你能看到吗?

答案 1 :(得分:1)

另一种看到此算法实际上是O(k)时间的方法是:

让所有节点最初都是白色的。如果通过调用kSmaller()来增加count来访问节点,则将节点着色为黑色;如果通过调用kSmaller()而不会增加count来访问节点则为灰色}}。当count没有递增时,递归停止,因此灰色节点下的每个节点都必须是白色; OTOH,黑色节点的每个孩子都必须是黑色或灰色。显然,确实存在count个黑色节点,并且由于每个节点最多有2个子节点,因此最多可以有count * 2个灰色节点,因此访问最多count * 3个(即黑色或灰色)节点整体。由于count显然始终保持< = k,因此访问的节点不超过3k。最后,由于每次调用只完成O(1)工作(在递归调用中花费的时间之外),总体时间复杂度最差为O(k)。