【问题标题】:Issue checking if binary tree is also binary search tree检查二叉树是否也是二叉搜索树的问题
【发布时间】:2018-05-16 12:30:32
【问题描述】:

我正在尝试解决这个问题,但我遇到了一些麻烦:

在二叉搜索树 (BST) 中:

  • 节点左子树中每个节点的数据值都小于该节点的数据值。
  • 节点右子树中每个节点的数据值都大于该节点的数据值。

给定根节点:

class Node {
    int data;
    Node left;
    Node right;
}

判断二叉树是否也是二叉搜索树

我有这个代码:

boolean check(Node root) {   

    //node doesn't have any children
    if (root.left == null && root.right == null) {
        return true;
    }

    boolean leftIsBst = true;
    boolean rightIsBst = true;

    if (root.left != null) {
        leftIsBst = (root.left.data < root.data) && check(root.left);
    }

    if (root.right != null) {
        rightIsBst = (root.right.data > root.data) && check(root.right);
    }

    return leftIsBst && rightIsBst;
}

这在某些情况下有效,但在这种情况下会失败:

如你所见,节点(4)在节点(3)的左子树中,虽然4大于3,所以该方法应该返回@ 987654325@。不过,我的代码返回 true

我该如何控制这种情况?如何检查左/右子树中的所有值是否小于/大于根(不仅是直接子树)?

【问题讨论】:

    标签: java algorithm binary-tree binary-search-tree


    【解决方案1】:

    BST 定义为:

    -节点的左子树总是包含值小于该节点的节点。 - 节点的右子树总是包含值大于该节点值的节点。 -左右子树也是有效的BST。

        class Solution {
            public boolean isValidBST(TreeNode root) {
                return helper (root,Integer.MIN_VALUE,Integer.MAX_VALUE);
            }
            public boolean helper(TreeNode root,long low,long high){
                if (root==null){
                    return true;
                }
                if (root.val<low ||root.val>high){
                    return false;
                }
                return (helper(root.left,low,root.val-1) && 
        helper(root.right,root.val+1,high));
            }
        }
    

    【讨论】:

      【解决方案2】:

      您的定义是正确的(尽管您不一定需要坚持所有键都是不同的),但您的代码并未实现定义中的所有条件。具体来说,您不会强制每个子树中的最小值和最大值。

      这是一个实现您的定义的高效递归解决方案:

      boolean check(Node root) {
          return check(root, INT_MIN, INT_MAX);
      }
      boolean check(Node n, int minval, int maxval) {
          if (n == null) {
              return true;
          }
          return (
              n.data >= minval && n.data <= maxval &&
              check(n.left, minval, n.data-1) &&
              check(n.right, n.data+1, maxval)
          );
      }
      

      请注意,我没有费心检查n.data-1n.data+1 中的溢出,这是您在现实生活中必须要做的。如果您想允许重复键,只需将它们更改为n.data,您不必担心。

      【讨论】:

      • 天哪,这太疯狂了,它就像一个魅力,它是如此简单......谢谢!
      【解决方案3】:

      您的递归逻辑不正确。我在这里给出 cpp 逻辑。您可能需要将其翻译成 Java 代码。

      布尔检查(节点 *root){

      static Node *prev = NULL;
      
      if(root) {
      
          If(!check(root->left)) return false;
      
          If(prev != Null && prev->data > root->data) return false;
      
          Prev = root;
      
          return check(root->right);
      
      
      }
      
      return true;
      

      }

      【讨论】:

      • 只需将 NULL 替换为 null,删除星号并将 -> 替换为点。你有你的java代码
      • 人们无缘无故地给出-1。我们无视 stackoverflow 帮助人们解决问题的意图。我对人们对我的回答的反应感到非常失望。这难道不是他所问问题的解决方案,不会导致他期待的答案吗?
      【解决方案4】:

      类似下面的东西应该可以工作

      boolean check(Node root) {   
      
          if (root == null) {
              return true;
          }
      
      
          if (root.left != null && max(root.left) > root.data  ) {
              return false
          }
      
          if (root.right != null && max(root.right) < root.data ) {
              return false;
          }
      
          return check(root.left) && check(root.right);
      }
      

      注意:

      • 这是相当低效的
      • 你需要实现max()

      【讨论】:

      • Matt Timmermans 的解决方案在概念上是相同的,但效率更高。
      • 我已经测试了您的解决方案并且它正在工作,但您是对的,它并没有那么高效。不管怎样,谢谢你! +1
      • 是的,最大逻辑很昂贵。
      猜你喜欢
      • 2019-04-09
      • 1970-01-01
      • 1970-01-01
      • 2012-06-05
      • 2017-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多