【问题标题】:Find root of minimal height which is not BST找到不是 BST 的最小高度的根
【发布时间】:2015-06-21 18:01:48
【问题描述】:

我正在努力解决以下问题:

编写函数,对于给定的二叉树返回一个最小高度的根,当树是 BST 时不是 BST 或 NIL。

我知道如何检查树是否为 BST,但不知道如何重写它。 我将不胜感激伪代码中的算法。

【问题讨论】:

  • 我不明白这个问题;据我了解,任何一棵树都只有一个根。请澄清。
  • 我的意思是这种最小子树的根,它是我们二叉树中的一个节点

标签: algorithm data-structures tree binary-tree binary-search-tree


【解决方案1】:

与其直接跳入在这里工作的算法,我想给出一系列观察结果,最终得出一个非常好的算法来解决这个问题。

首先,假设对于树中的每个节点,您都知道以该节点为根的子树中的最大值和最小值。 (让我们将它们表示为 min(x) 和 max(x),其中 x 是树中的一个节点)。鉴于此信息,我们可以进行以下观察:

观察 1: 如果 x ≤ max(x.left) 或 x ≥ min(y.right),则节点 x 是非 BST 的根

这不是一个 if-and-only-if 条件 - 它只是一个“如果” - 但它是一个有用的观察。这样做的原因是,如果 x ≤ max(x.left),那么 x 的左子树中有一个不小于 x 的节点,这意味着以 x 为根的树不是 BST,并且如果 x > min( x.right),那么 x 的右子树中有一个不大于 x 的节点,这意味着以 x 为根的树不是 BST。

现在,x max(x.left) 的任何节点不一定是 BST 的根。以这棵树为例:

              4
             / \
            1   6
           /     \
          2       5

这里,根节点大于其左子树中的所有内容,并且小于其右子树中的所有内容,但整个树本身不是 BST。原因是植根于 1 和 6 的树不是 BST。这导致了一个有用的观察:

观察 2: 如果 x > max(x.left) 且 x

这个结果的证明的简单草图:如果 x.left 和 x.right 是 BST,那么对树进行中序遍历将列出 x.left 中的所有值以升序排列,然后是 x,然后x.right 中的所有值按升序排列。由于 x > max(x.left) 和 x

这两个属性提供了一种非常好的方法来查找树中不是 BST 根的每个节点。思路是从叶子向上遍历树中的节点,检查每个节点的值是否大于其左子树的最大值且小于其右子树的最小值,然后检查其左右子树是否为BST .您可以通过后序遍历来做到这一点,如下所示:

 /* Does a postorder traversal of the tree, tagging each node with its
  * subtree min, subtree max, and whether the node is the root of a
  * BST.
  */
 function findNonBSTs(r) {
     /* Edge case for an empty tree. */
     if (r is null) return;

     /* Process children - this is a postorder traversal. This also
      * tags each child with information about its min and max values
      * and whether it's a BST.
      */
     findNonBSTs(r.left);
     findNonBSTs(r.right);

     /* If either subtree isn't a BST, we're done. */
     if ((r.left  != null && !r.left.isBST) ||
         (r.right != null && !r.right.isBST)) {
        r.isBST = false;
        return;
     }

     /* Otherwise, both children are BSTs. Check against the min and
      * max values of those subtrees to make sure we're in range.
      */
     if ((r.left  != null && r.left.max  >= r.value) ||
         (r.right != null && r.right.min <= r.value)) {
        r.isBST = false;
        return;
     }

     /* Otherwise, we're a BST, and our min and max value can be
      * computed from the left and right children.
      */
     r.isBST = true;
     r.min = (r.left  != null? r.left.min  : r.value);
     r.max = (r.right != null? r.right.max : r.value);
}

如果你在树上运行了这个过程,每个节点都将被标记为是否是二叉搜索树。从那里开始,您所要做的就是再次遍历树以找到不是 BST 的最深节点。我将把它作为一个众所周知的练习留给读者。 :-)

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-13
    • 2011-06-14
    • 2021-05-27
    • 1970-01-01
    • 2013-11-26
    • 2022-06-15
    • 2016-10-24
    相关资源
    最近更新 更多