设计一种算法,搜索两个AVL树之间的第k个最大元素

时间:2016-11-07 20:20:56

标签: algorithm tree binary-tree complexity-theory avl-tree

这是上周讲座中提出的一个挑战性问题,自那以后我一直在考虑它。我们被要求创建一种算法,在两个AVL树之间搜索第k个最大元素。两棵树中的每个节点都包含两条信息:它的整数值和它在子树中包含的子项的数量(因此一个叶子将有一个子元素)。算法的复杂性不能低于O((logn)^ 2)。

我想过将一棵树中的每个节点与另一棵树中的每个节点进行比较,但这样的O(n)复杂度太慢了。

2 个答案:

答案 0 :(得分:1)

作为第一步,设计一个函数,对于给定的上限 b ,确定当 b 时,AVL树中的元素数量会减少:

count(node, b)
    if node.key < b:
        return node.left.size + 1 + count(node.right, b)
    else
        return count(node.left, b)

每个分支中只有一个递归调用,并且每次调用时节点的深度都会增加。所以这个函数的复杂性是O(log(n))。

现在我们可以使用count

构建所需的函数
kth(k, node1, tree2)
     left = node1.left.size + count(tree2, node1.key)
     if k < left:
        return kth(k, node.left, node2.right
     else if k == left:
         return max(upperBound(tree2, node1.key), upperBound(node1.left, node1.key))
     else if k == left + 1:
         return node1.key
     else
         return kth(k - node1.left.size - 1, tree2)

对于这个函数node1在每次递归调用中也增加了,所以我们有 O(log n)调用,每个调用需要 O(log n)时间由于调用count函数。根据需要,总运行时间为 O(log²n)

要完成此解决方案,需要设计应返回子树中最大键的函数upperBound。这可以在 o(log n)时间内轻松完成。

答案 1 :(得分:0)

假设k-th元素位于第一个树中。我们可以二元搜索它在树中的位置。对于固定位置p,我们可以在p-th时间内找到树中的O(log n)元素(从根开始,向右移动,具体取决于左子树的大小) 。

现在我们需要找到第二个树中小于此元素的元素数。我们可以在O(log n)时间从根开始,向左或向右移动,具体取决于当前节点中的值(当我们向右移动时,将左子树的大小添加到答案中) 。

当我们知道第二棵树中小于给定元素的元素数量时(让我们称这个数字为s),我们知道它在树的联合中的位置正好是{{ 1}}。

此算法在s + p时间内运行。

如果第O(log^2 n)个元素不在第一个树中,则它必须位于第二个树中。因此,我们在另一棵树上重复这个过程来得到一般情况下的答案。