检查二叉树是不是也是二叉搜索树的问题

Posted

技术标签:

【中文标题】检查二叉树是不是也是二叉搜索树的问题【英文标题】: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

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

【问题讨论】:

【参考方案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。我们无视 *** 帮助人们解决问题的意图。我对人们对我的回答的反应感到非常失望。这难道不是他所问问题的解决方案,不会导致他期待的答案吗?【参考方案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 是的,最大逻辑很昂贵。

以上是关于检查二叉树是不是也是二叉搜索树的问题的主要内容,如果未能解决你的问题,请参考以下文章

二叉树:我是不是一棵二叉搜索树

二叉树23:二叉搜索树的几道题

二叉搜索树

二叉搜索树的简易实现

二叉树

二叉树之二叉搜索树(BSTree)