(二叉树):验证二叉搜索树

题目描述:

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
x x 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 {
public:
    vector<int>res;
    bool isValidBST(TreeNode* root) {

        if(!root)return true;       
        searchBST(root);
        for(int i=0;i<res.size()-1;i++)
            if(res[i]>=res[i+1])return false;
        return true;
}
    void searchBST(TreeNode* root)
    {
        if(root==NULL)return;
        searchBST(root->left);
        res.push_back(root->val);
        searchBST(root->right);
        return;
    }

另外一种方法即是通过递归进行,我之前自己写了一个递归算法,发现失败了,失败的原因是只考虑到了当前结点和左子结点与右子结点的关系,没有考虑整个左子树或右子树的与双亲结点的关系,这也是一个需要特别注意的地方。最后参考了别人的一种递归算法,发现很巧妙,代码如下:

class Solution {
public:
    bool isValidBST(TreeNode* root) {
         return isValidBST(root,INT_MAX,INT_MIN);
    }
bool isValidBST(TreeNode* root, long left, long right){
        if(!root)return true;
        if(root->val<=left||root->val>=right)return false;
        return isValidBST(root->left,left,root->val)&&isValidBST(root->right,root->val,right);
    }
};

这段程序是对isValidBST函数进行了重载,重载后的函数功能是:通过left和right来判断当前结点值是否位于二者之间,如果是,就继续判断左子结点和右子结点,否则说明当前结点不满足搜索二叉树的定义,返回false,如果递归搜索到了null结点,说明在递归的这条路径上的所有结点都满足搜索二叉树的定义,自然就返回true了。那么为什么说这个递归很巧妙呢?巧妙就在于递归时的参数传递上,这里参数的传递很巧妙的保证了当前结点的左子树都比当前结点小,右子树比当前结点大,如何保证的呢?下面画个图来分析一下:
在这里插入图片描述
根据图可以看到,对于斜树上的结点来说,是只有一个限定值的,即2、4结点只能确定上限值为其双亲结点值,3、7、11则只能确定下限值为其双亲结点值;对于非斜树上的结点来说,左子结点6、8、10除了要小于其双亲结点值,还应当大于其“爷爷”结点值,而这恰好就是其双亲结点的下限值,因此左子结点的上限为其双亲结点值,而下限为其双亲结点的下限值;右子结点5、9除了要大于其双亲结点值,还应当小于其“爷爷”结点值,而这恰好就是其双亲结点的上限值,因此右子结点的下限为其双亲结点值,而上限为其双亲结点的上限值。同样也可以将对应的下限值和上限值加到斜树上的左子结点和右子结点上。因此在程序中对于左子结点则left=left,right=val,对于右结点则left=val,right=right。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值