[LeetCode] 98、验证二叉搜索树

题目描述

给定一个二叉树,判断其是否是一个有效的二叉搜索树。

假设一个二叉搜索树具有如下特征:

  • 节点的左子树只包含小于当前节点的数。
  • 节点的右子树只包含大于当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

解题思路

二叉搜索树是递归定义的,所以也可以递归验证。(cf:《剑指offer》第55题,验证平衡二叉树,书上的“后序遍历”验证法代码不好,参考博客

这个题不要以为简单:乍一看,以为这是一个平凡的问题。只需要遍历整棵树,检查 node->right->val > node->valnode->left->val < node->val对每个结点是否成立。**这是不对的!!!**因为不仅右子结点要大于该节点,整个右子树的元素都应该大于该节点(这是个坑,错过一次了)。如下:

   10
   / \
  5  15
     / \
    6  20

这意味着我们需要在遍历树的同时保留结点的上界下界,在比较时不仅比较子结点的值,也要与上下界比较。主要有两种方法:

  • 递归法:通过限定每个节点值的范围来验证二叉搜索树。(题解

    • 遍历节点root时,给出root值的范围 ( m i n v , m a x v ) (minv,maxv) (minv,maxv), m i n v < r o o t . v a l < m a x v minv < root.val < maxv minv<root.val<maxv,当 r o o t . v a l root.val root.val超出 范围 ( m i n v , m a x v ) (minv,maxv) (minv,maxv) 时,就不算二叉搜索树了。
    • 递归左子树时,左子树的最大值不能超过 r o o t . v a l root.val root.val
    • 递归左子树时,右子树的最小值不能小于 r o o t . v a l root.val root.val
    class Solution {
    public:
        bool isValidBST(TreeNode* root) {
            if(root == nullptr)
                return true;
            
            return verifyRecursively(root, LONG_MIN, LONG_MAX);
        }
        
        bool verifyRecursively(TreeNode* pNode, long left_min, long right_max){
            if(pNode == nullptr)
                return true;
            if(pNode->val <= left_min || pNode->val >= right_max)
                return false;
            
            return verifyRecursively(pNode->left, left_min, pNode->val) &&
                   verifyRecursively(pNode->right, pNode->val, right_max);
        }
    };
    
  • 中序遍历法:因为二叉搜索树中序遍历是递增的,所以我们可以中序遍历判断前一数是否小于后一个数。(评论板块

参考代码

上面给出了“利用最大值最小值”的解法,下面是利用“中序遍历”的解法。

class Solution {
public:
    TreeNode* pre;
    bool isValidBST(TreeNode* root) {
        //方法一 非递归
        stack<TreeNode*> s;
        TreeNode* cur = root;  
        while(!s.empty() || cur){
            if(cur){
                s.push(cur);
                cur = cur->left;
            }else{
                cur = s.top();
                s.pop();
                if(pre && pre->val >= cur->val) return false;
                pre = cur;
                cur = cur->right;
            }
        }
        return true;
        
        //方法二 递归
        if(root == NULL)
            return true;
        if(!isValidBST(root->left))
            return false;
        
        if(pre && pre->val >= root->val)
            return false;
        pre = root;
        
        if(!isValidBST(root->right))
            return false;  
        return true;
         
    }

};

完整的“中序遍历”递归代码

class Solution {
public:
    bool isValidBST(TreeNode* root) {
    	// 递归出口,注意空树也是二叉搜索树
        if(root == nullptr)
            return true;
        
        bool left = isValidBST(root->left);
        
        if(pPre && pPre->val >= root->val)
            return false;
        pPre = root;
        
        bool right = isValidBST(root->right);
        
        return left && right;
    }
    
private:
    TreeNode* pPre = nullptr;
};
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值