二叉搜索树中缺少数字

时间:2016-05-16 06:45:08

标签: algorithm binary-search-tree

如果我的订单统计二进制平衡树有find(x)个不同的整数作为其键,我想编写函数 x ,它返回不在的最小整数树,大于O(log(n))。在6,7,8,10,11,13,14时间。

例如,如果树中的键是find(6)=9,那么find(8)=9find(10)=12find(13)=15max

我考虑在O(log(n))中找到x,在i_x中找到O(log(n))(标记为i_x=n-(m-x))的索引,然后max+1我可以简单地返回6,7,8,10,11,13,14

索引我的意思是在中,索引6为0,索引10为3,例如......

但我在其他案件中遇到麻烦......

2 个答案:

答案 0 :(得分:2)

根据wikipedia,订单统计树在log(n)时间内支持这两项操作:

  • 选择(i) - 在O(log(n))中找到存储在树中的第i个最小元素
  • Rank(x) - 在树中查找元素x的等级,即在O(log(n))
  • 中树的元素的排序列表中的索引

首先获得x的等级,然后选择x的高级等级,直到找到插入缺失元素的位置。但这有最坏情况的n * log(n)。

相反,一旦你获得了x的等级,你就会进行一种二分搜索。基本思想是树中的数字x和y之间是否存在空格。如果rank(x) - rank(y) != x - y,则会有一个空格。

一般情况是:当搜索区间中的数字[lo,hi](lo和hi是树中的等级,mid是中间等级),如果lo和mid之间有空格则在内部搜索[ lo,mid],否则在[mid,hi]内搜索。 你最终会找到你寻找的号码。

但是,此解决方案不会在log(n)时间内运行,而是在log ^ 2(n)中运行。这是我能想到的最佳解决方案。

编辑:

嗯,这是一个棘手的问题,我多次改变主意。以下是我提出的建议:

我假设左节点保持较低值,右节点保持优值

find(x)的直觉:从根目录开始,沿着树几乎,就像在标准二叉树中一样。如果我们要去的分支不包含find(x)的解决方案,则将其删除。

我们将首先介绍基本案例:

  • 如果我找到的节点为null,那么我就完成了,然后返回我想要的值。
  • 如果当前值小于我要查找的值,我会在右子树中搜索x
  • 如果我发现节点包含x,那么我在右子树上搜索x + 1。

x在左子树中的情况比较棘手,因为它可能包含x,x + 1,x + 2,x + 3等,直到y-1,其中y是存储在当前节点中的值。在这种情况下,我们希望在右子树中搜索y + 1。

但是,如果从x到y的所有数字都不在左子树中(也就是说,存在间隙),那么我们将在其中找到一个值,因此我们查看x的左子树。

问题是:如何查找子树中是否存在从x到y的序列?

python中的算法如下所示:

def find(node, x):
    if node == null:
        return x
    if node.data < x:
        return find(node.right, x)
    if node.data == x:
        return find(node.right, x+1)
    if is_full(...):
        return find(node.right, node.data+1)
    return find(node.left, x)

要获得严格大于x的最小值(不在树中),第一个调用是find(root, x+1)。如果您希望最大值大于或等于不在树中的x,则第一个调用为find(root, x)is_full方法检查左子树是否包含从x到node.data-1的所有数字。

现在,以此为出发点,我相信您可以自己找到合适的解决方案,使用每个子树中包含的节点数存储在子树根中的事实。

答案 1 :(得分:1)

我遇到了类似的问题。

找到大于x的内容没有任何限制,只需找到BST中缺少的元素。

以下是我的答案,完全有可能在O(lg(n))时间内这样做,假设树几乎是平衡的。您可能需要考虑随机构建的BST的预期高度为lg(n)给定n元素的证明。我使用更简单的表示法O(h),其中h =树的高度,所以现在有两件事是分开的。

假设和/或要求:

  1. 我增强了数据结构。在每个节点存储(left_subtree + right_subtree + 1)的计数。
  2. 显然,单个节点的数量是1
  3. 此计数是预先计算并存储在每个节点
  4. enter image description here

    请原谅我的多个符号不等于(=/=!=

    另请注意,如果要在计算机上编写工作代码,代码可能会以更好的方式构建。

    此外,我认为,在这个时间点,这是正确的。我尝试了尽可能多的角落案例,总的来说它有效。即使有一个反例,我也不认为修改代码以适应特定情况会很困难;但请评论反例,我感兴趣。