• 【LeetCode】98. 验证二叉搜索树(递归+中序遍历,Java实现,上下界详细图解)


    题目

    image-20200620174924052

    解析

    方法一:中序遍历

    二叉搜索树「中序遍历」得到的值构成的序列一定是升序的

    中序遍历时,判断当前节点是否大于中序遍历的前一个节点,如果大于,说明满足 BST,继续遍历;否则直接返回 false。

    class Solution {
        long pre = Long.MIN_VALUE;
        public boolean isValidBST(TreeNode root) {
            if (root == null) {
                return true;
            }
            // 访问左子树
            if (!isValidBST(root.left)) {
                return false;
            }
            // 访问当前节点:如果当前节点小于等于中序遍历的前一个节点,说明不满足BST,返回 false;否则继续遍历。
            if (root.val <= pre) {
                return false;
            }
            pre = root.val;
            // 访问右子树
            return isValidBST(root.right);
        }
    }
    
    

    方法二:递归(上界和下界)

    首先,我们来看二叉搜索树的两个特征:

    • 节点的左子树只包含小于当前节点的数。
    • 节点的右子树只包含大于当前节点的数。

    仔细思考这两句话,你可以理解为:

    • 当前节点的值是其左子树的值的上界(最大值)
    • 当前节点的值是其右子树的值的下界(最小值)

    有了这个想法,你可以将验证二叉搜索树的过程抽象成下图(-00代表无穷小,+00代表无穷大):

    验证二叉搜索树.png

    有了这个图,你可以很清晰地将这个判断过程抽象成递归代码。

    但是在给出代码之前,我们看一看写递归代码必需的两个要素:

    • 终止条件
    • 深入递归的递归方程

    首先来看在这道题中的终止两种终止条件:

    • 当当前节点为空时,表示这个节点已经是叶子节点,这个节点没有子节点,可以返回 True
    • 当当前节点不在 [ min_value,max_value ] 的区间时,这个节点不能同时符合二叉搜索树的两个特征,返回 False

    然后看看递归方程,由于节点有两个子树,所以我们有两个递归方程要执行:

    • 对左子树:helper(node.left, lower, val)解释:当前节点是左子树的上界(你可以粗略地理解为最大值)
    • 对右子树:helper(node.right, val, upper) 解释:当前节点值是右子树的下界,并且继承上一个节点的上界。
      这个递归过程是最难理解的地方,如果不理解,你可以看一看上图中绿色剪头,你会很快理解这么递归的原因。

    代码如下

    class Solution {
      public boolean helper(TreeNode node, Integer lower, Integer upper) {
        if (node == null) return true;
    
        int val = node.val;
        if (lower != null && val <= lower) return false;
        if (upper != null && val >= upper) return false;
    
        if (! helper(node.right, val, upper)) return false;
        if (! helper(node.left, lower, val)) return false;
        return true;
      }
    
      public boolean isValidBST(TreeNode root) {
        return helper(root, null, null);
      }
    }
    
    
    

    复杂度分析

    时间复杂度 : O(n),其中 n为二叉树的节点个数。在递归调用的时候二叉树的每个节点最多被访问一次,因此时间复杂度为 O(n)。

    空间复杂度 : O(n),其中 n 为二叉树的节点个数。递归函数在递归过程中需要为每一层递归函数分配栈空间,所以这里需要额外的空间且该空间取决于递归的深度,即二叉树的高度。最坏情况下二叉树为一条链,树的高度为 n ,递归最深达到 n 层,故最坏情况下空间复杂度为 O(n) 。
    递归过程中需要为每一层递归函数分配栈空间,所以这里需要额外的空间且该空间取决于递归的深度,即二叉树的高度。最坏情况下二叉树为一条链,树的高度为 n ,递归最深达到 n 层,故最坏情况下空间复杂度为 O(n) 。

  • 相关阅读:
    创建型模式
    创建、修改、删除表总结
    分页式存储管理及地址转换(网易笔试题)
    二进制、十进制、十六进制相互转换
    转 String,StringBuffer与StringBuilder的区别??
    IDEA 修改某个Module名称
    IDEA Git 修改后的文件无法Commit
    git git push某一次的commit记录
    git merge 结果是 git merge Already up-to-date. 该怎么解决?
    火币网API文档——REST 行情、交易API简介
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13308052.html
Copyright © 2020-2023  润新知