LeetCode 98. Validate Binary Search Tree(判断是否为二叉搜索树,C++,python)

98. Validate Binary Search Tree
Given a binary tree, determine if it is a valid binary search tree (BST).

Assume a BST is defined as follows:

  • The left subtree of a node contains only nodes with keys less than(严格小)
    the node’s key.
  • The right subtree of a node contains only nodes with keys greater
    than(严格大)
    the node’s key.
  • Both the left and right subtrees must also be binary search trees.

Example 1:

Input:

    2
   / \
  1   3

Output: true

Example 2:

    5
   / \
  1   4
     / \
    3   6

Output: false

Explanation: The input is: [5,1,4,null,null,3,6]. The root node’s value is 5 but its right child’s value is 4.

思路:二叉搜索树就是左子树中的节点比根节点小,右子树中节点值比根节点大。看到和树相关的题目很自然会想到递归的做法。根据二叉搜索树的性质,可以递归地判断当前节点作为根节点其左孩子是否比根节点小,并且其右孩子是否比根节点大。 于是可以写出如下的程序。

class Solution(object):
    def isValidBST(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        return self.validBST(root)
    
    def validBST(self, root):
        if root == None:
            return True
        
        leftNode = root.left
        rightNode = root.right
        if leftNode and leftNode.val >= root.val:
            return False
        if rightNode and rightNode.val <= root.val:
            return False
        return self.validBST(leftNode) and self.validBST(rightNode)

但是你会看到:
在这里插入图片描述

这里这个6虽然小于15,但是6比根节点10小。而二叉搜索树的所有右子树应该比根节点大。所以上面这种只判断一个由3个节点构成的子树是否符合二叉搜索树的性质是不行的,只考虑了局部,没有考察整体。
在这里插入图片描述
上面的思路行不通,我们必须换一个思路。其实从上面的比较中发现,二叉搜索树其实可以看成一个节点的数值是否在某个区间内。所以我们转换思路。首先根节点的范围没有限制,只要在正负无穷之间即可,而其左子树应该比根节点的值小,所以左子树属于的区间应该小于根节点的值;右子树应该比根节点的值大,所以右子树属于的区间应该大于根节点的值。 一个例子如下图,可以看到节点6不属于区间(10, 15),所以这棵树不是二叉搜索树。
在这里插入图片描述
上面思路的python实现:

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def isValidBST(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        return self.validBST(root, -float('inf'), float('inf'))
    
    def validBST(self, root, left, right):
        if root == None:
            return True
        leftNode = root.left
        rightNode = root.right
        rootVal = root.val
        if rootVal<=left or rootVal>=right:
            return False
        return self.validBST(leftNode, left, rootVal) and self.validBST(rightNode, rootVal, right)

结果:在这里插入图片描述

c++实现:
不得不提一下,如果你自己用c++尝试了这题,应该会发现这题很多数据点设计的很巧妙,很多地方会涉及无穷大无穷小,一不小心容易造成溢出。python中可以用float('inf')表示无穷大,-float('inf')表示无穷小,而c++中并没有绝对的无穷大,刚好这题节点的数值只是int类型,所以不能用INT_MAXINT_MIN,而换成INT64_MAXINT64_MIN即可。上面这种做法在数据能达到INT64_MAXINT64_MIN时就不行了。后面我自己写了个重载运算符来间接实现无穷大无穷小,有些麻烦,不过能做出来,而且数据更大应该也没问题。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */

class Solution {
public:
    bool binaryTree = true;
    
    bool isValidBST(TreeNode* root) {
        validBST(root, INT64_MIN, INT64_MAX);//INT64_MIN, INT64_MAX
        return binaryTree;
    }
    
    void validBST(TreeNode* root, long left, long right){//long
        if(root == NULL)
            return;
        TreeNode* leftNode = root->left;
        TreeNode* rightNode = root->right;
        if(root->val<=left || root->val>=right)//看成开区间
        {
            binaryTree = false;
            return;
        }
        validBST(leftNode, left, root->val);//如果是int 不能减一root-val-1
        validBST(rightNode, root->val, right);//如果是int 不能加一root->val+1数据可能会溢出
    }
};

结果
在这里插入图片描述

另一个版本,有点复杂,但是适用性更强,上面的方法对这题已经OK。有兴趣可以看看,个人能力有限,欢迎提出更简单的方法。。。

class Myint{
public:
    Myint(int type, int val = 0){
        this->type = type;
        this->val = val;
    }
    bool operator<=(int val){
        if(type == 1)//无穷大
        {
            return false;//无穷大不比任何数小
        }
        else if(type == 0){
            return true;//无穷小比任何数小
        }
        else{
            return this->val<=val;//此时Myint表示一个普通整数
        }
    }
    bool operator<=(Myint myint){
        if(type == 1)//无穷大
        {
            return false;//无穷大不比任何数小
        }
        else if(type == 0){
            return true;
        }
        else{
            return this->val<=myint.getVal();
        }
    }
    bool operator>=(int val){
        if(type == 1){
            return true;//无穷大比任何数大
        }
        else if(type == 0){
            return false;//无穷小比任何数小
        }
        else{
            return this->val>=val;
        }
    }
    
    bool operator>=(Myint myint){
        if(type == 1){
            return true;//无穷大比任何数大
        }
        else if(type == 0){
            return false;//无穷小比任何数小
        }
        else{
            return this->val>=myint.getVal();
        }
    }
    int getVal(){
        return val;
    }
private:
    int type;
    int val;
};

class Solution {
public:
    bool binaryTree = true;
    
    bool isValidBST(TreeNode* root) {
        Myint myMax(1);//表示无穷大无穷小第二个参数不用赋值,没有用到
        Myint myMin(0);
        if(root && root->left==NULL && root->right==NULL)//只有根节点
        {
            binaryTree = true;
            return binaryTree;
        }
        validBST(root, myMin, myMax);
        return binaryTree;
    }
    
    void validBST(TreeNode* root, Myint left, Myint right){
        if(root == NULL)
            return;
        TreeNode* leftNode = root->left;
        TreeNode* rightNode = root->right;
        if(left>=root->val || right<=root->val)//看成开区间
        {
            binaryTree = false;
            return;
        }
        Myint rootVal(2, root->val);
        validBST(leftNode, left, rootVal);//不能减一root-val-1
        validBST(rightNode, rootVal, right);//不能加一root->val+1数据可能会溢出,看成开区间
    } 
};

结果:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值