LeetCode 98.验证二叉搜索树(Java,递归法,中序遍历法)

题目描述

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

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

  • 节点的左子树只包含小于当前节点的数。
  • 节点的右子树只包含大于当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。
    在这里插入图片描述

解法1-递归法

解题思路:根据二叉搜索树的特点我们可以知道,根结点的左子树的所有结点的值都小于根结点的值,即根结点的值是左子树值的上界;根结点的右子树的所有结点的值都大于根结点的值,即根结点的值是左子树值的下界。受此启发,我们可以设计一个函数 h e l p e r ( r o o t , l o w e r , u p p e r ) helper(root,lower,upper) helper(root,lower,upper),来判断当前结点的值是否在 ( l o w e r , u p p e r ) (lower,upper) (lower,upper)的范围内,注意,此处是开区间。如果不满足条件,说明不是二叉搜索树,否则继续递归调用 h e l p e r helper helper函数检查它的左右子树是否满足二叉搜索树的条件。

class Solution {
    public boolean helper(TreeNode root, double lower, double upper) 
    {
        if(root != null)    //如果结点为空,直接返回true
        {
            //如果当前结点的值不在(lower,upper)的范围内,则不是二叉搜索树
            if(root.val <= lower || root.val >= upper)
                return false;
            //继续检查左子树,注意此时上界变为当前结点的值
            if(!helper(root.left, lower, root.val))
                return false;
            //继续检查右子树,注意此时下界变为当前结点的值
            if(!helper(root.right, root.val, upper))
                return false;

            //如果当前结点,以及其左右子树都满足条件,返回true
            return true;
        }
        return true;
    }

    public boolean isValidBST(TreeNode root) {
        var inf = Double.MAX_VALUE;
        return helper(root, -inf, inf);
    }
}

复杂度

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n为二叉树的结点个数。因为在递归过程中二叉树的每个结点最多被访问一次,所以为 O ( n ) O(n) O(n),和递归遍历二叉树的时间复杂度一样。
  • 空间复杂度:因为递归用到了栈空间,所需的辅助空间为二叉树的深度,最坏情况下为 O ( n ) O(n) O(n),即二叉树为一条链的情况。

解法2-中序遍历法

解题思路:根据二叉搜索树的特性我们可知,二叉搜索树的中序遍历得到的序列一定是升序的。因此,我们可以对二叉搜索树进行中序遍历,在每次访问根结点时,将其值与之前结点的最大值进行比较,若小于之前结点的最大值,则说明不是二叉搜索树。

class Solution {
    public boolean isValidBST(TreeNode root) {
        var stack = new Stack<TreeNode>();
        double pre = - Double.MAX_VALUE;
        TreeNode p = root;
		
		//思路和二叉树的中序遍历一样,仅仅是多了一个根结点的值和之前结点最大值的比较
        while(p != null || !stack.empty())
        {
            if(p != null)
            {
                stack.push(p);
                p = p.left;
            }
            else
            {
                p = stack.pop();
                //如果当前结点的值不大于之前结点的最大值,则不是二叉搜索树
                if(p.val <= pre)
                    return false;
                pre = p.val;
                p = p.right;
            }
        }
        return true;
    }
}

复杂度

  • 时间复杂度: O ( n ) O(n) O(n),因为在每个结点最多被访问一次,所以为 O ( n ) O(n) O(n)
  • 空间复杂度:因为用到了栈空间,所需的辅助空间为二叉树的深度,最坏情况下为 O ( n ) O(n) O(n),即二叉树为一条链的情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值