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

379 阅读1分钟

题目

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) 。