【问题标题】:Missing number in binary search tree二叉搜索树中缺少数字
【发布时间】:2016-05-16 06:45:07
【问题描述】:

如果我有以 n 不同整数作为键的顺序统计二叉平衡树,并且我想编写函数 find(x) 来返回不在树中的最小整数,并且大于x。在O(log(n)) 时间。

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

我想在O(log(n)) 中找到maxx 的索引(标记i_x)在O(log(n)) 然后如果i_x=n-(m-x) 那么我可以简单地返回max+1

我的意思是在6,7,8,10,11,13,14 中,索引 6 为 0,例如索引 10 为 3...

但我在其他情况下遇到了麻烦......

【问题讨论】:

  • 像往常一样查找 x。然后从 x 执行深度优先样式搜索,使得每个整数都是前一个整数的增量。如果不是,那么你找到了你的整数。
  • @Striker 但是对于1,2,3,4,5,6,7,9find(1) 来说,应该是O(n),不是吗?
  • 最坏的情况是 O (n)。
  • @Striker 和我需要O(log(n))... 我们如何使用它是一个订单统计树这一事实?
  • @Striker,你的想法是正确的,进一步利用 BST 属性可以在 O(h) 时间,其中 h = 树的高度,在最坏的情况下无论如何都是 O(n)。所以你的评论实际上是答案的线索。在下面找到一个调谐的。

标签: algorithm binary-search-tree


【解决方案1】:

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

  • Select(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是树中的rank,mid是中间的rank),如果lo和mid之间有空格则在[ lo,mid],否则在 [mid, hi] 内搜索。 你最终会找到你要找的号码。

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

编辑:

嗯,这是一个棘手的问题,我改变了好几次主意。这是我想出的:

我假设左节点的价值较低,而右节点的价值较高

find(x) 的直觉:从根开始,沿着树向下几乎就像在标准二叉树中一样。如果我们要走的分支不包含find(x)的解,那就剪掉吧。

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

  • 如果我找到的节点为空,那么我就完成了,我返回我正在寻找的值。
  • 如果当前值小于我要查找的值,则在右子树中搜索 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 的所有数字。

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

【讨论】:

  • 我认为我们应该使用“树的节点需要存储一个附加值,即以该节点为根的子树的大小”这一事实,并使用它来创建函数@ 987654329@...
  • 好点,我忘了这个。那么直觉很简单。遵循经典 BST 中的路径。如果您想跟随左侧链接,则通过检查左侧的子值及其包含的节点数来检查是否缺少 int。如果有空格,则正常点击左侧链接。如果没有,向右走。
  • 从根目录跟随?或来自x?如果来自x,那么我什至可能需要“向上”边缘...
  • 从根目录搜索 x 就像在通常的 BST 中一样
  • 能否详细说明?
【解决方案2】:

我遇到了类似的问题。

查找大于某些x 没有任何限制,只需在BST 中查找缺失的元素即可。

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

假设和/或要求:

  1. 我增强了数据结构。在每个节点存储(left_subtree + right_subtree + 1) 的计数。
  2. 显然,单个节点的计数为1
  3. 此计数已预先计算并存储在每个节点中

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

还要注意,如果要在机器上编写工作代码,代码的结构可能会稍微好一点。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    • 1970-01-01
    相关资源
    最近更新 更多