当前位置:   article > 正文

验证二叉搜索树

验证二叉搜索树

题目介绍

力扣98题:https://leetcode-cn.com/problems/validate-binary-search-tree/
给定一个二叉树,判断其是否是一个有效的二叉搜索树。

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

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

分析

按照二叉搜索树的性质,我们可以想到需要递归地进行判断。这里需要注意的是,如果二叉搜索树的左右子树不为空,那么左子树中的所有节点,值都应该小于根节点;同样右子树中所有节点,值都大于根节点。

方法一:先序遍历

容易想到的方法是,用先序遍历的思路,自顶向下进行遍历。对于每一个节点,先判断它的左右子节点,和当前节点值是否符合大小关系;然后再递归地判断左子树和右子树。

这里需要注意,仅有当前的节点作为参数,做递归调用是不够的。当前节点如果是父节点的左子节点,那么以它为根的子树所有节点值必须小于父节点;如果是右子节点,则以它为根的子树所有节点值必须大于父节点。所以我们在递归时,还应该把取值范围的“上下界”信息传入。
代码演示如下

// 方法一:先序遍历
public boolean isValidBST1(TreeNode root){
    if (root == null) return true;

    return validator(root, null, null);
}

// 定义一个辅助校验器,用来传入上下界递归调用
public boolean validator(TreeNode root, Integer lowerBound, Integer upperBound){
    if (root == null) return true;

    // 1. 判断当前节点的值是否在上下界范围内,如果超出直接返回false
    if (lowerBound != null && root.val <= lowerBound)
        return false;
    if (upperBound != null && root.val >= upperBound)
        return false;

    // 2. 递归判断左右子树
    return validator(root.left, lowerBound, root.val) && validator(root.right, root.val, upperBound);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

复杂度分析

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

方法二:中序遍历

我们知道,对于二叉搜索树,左子树的节点的值均小于根节点的值,根节点的值均小于右子树的值。因此如果进行中序遍历,得到的序列一定是升序序列。所以我们的判断其实很简单:进行中序遍历,然后判断是否每个值都大于前一个值就可以了。

代码如下:

// 定义一个列表
ArrayList<Integer> inOrderArray = new ArrayList<>();

// 方法二:中序遍历
public boolean isValidBST(TreeNode root){
    // 1.中序遍历,得到升序数组
    inOrder(root);

    // 2. 遍历数组,判断是否升序
    for (int i = 0; i < inOrderArray.size(); i++){
        if (i > 0 && inOrderArray.get(i) <= inOrderArray.get(i-1))
            return false;
    }

    return true;
}

// 实现一个中序遍历的方法
public void inOrder(TreeNode root){
    if (root == null) return;

    inOrder(root.left);
    inOrderArray.add(root.val);
    inOrder(root.right);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

复杂度分析

  • 时间复杂度 : O(n),其中 n 为二叉树的节点个数。二叉树的每个节点最多被访问一次,因此时间复杂度为 O(n)。
  • 空间复杂度 : O(n),其中 n 为二叉树的节点个数。用到了额外的数组来保存中序遍历的结果,因此需要额外的 O(n) 的空间。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/615156
推荐阅读
相关标签
  

闽ICP备14008679号