LeetCode98 验证二叉搜索树 &《程序员面试金典》面试题 04.05. 合法二叉搜索树

LeetCode98 验证二叉搜索树 &《程序员面试金典》面试题 04.05. 合法二叉搜索树

题目

在这里插入图片描述

解题

如果该二叉树的左子树不为空,则左子树上所有节点的值均小于它的根节点的值; 若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值;它的左右子树也为二叉搜索树。

注意⚠️ ,是严格的小于和严格的大雨,换言之,如果出现重复值,判断为 false。

解题一:中序遍历

在这里插入图片描述
在这里插入图片描述

// javascript
// 声明全局变量,但不能在这里初始化
// 因为如果函数被调用多次,需要每次都初始化为 -Infinity
let lower;

var isValidBST = function(root) {
    lower = -Infinity; // 初始化为 -Infinity ⚠️
    return checkValidBST(root);
};

var checkValidBST = function(root) {
    if (root === null) return true;
    // 递归检查左子树 + 检查当前节点
    if (checkValidBST(root.left) === false || root.val <= lower) {
        return false;
    }
    // 更新 lower 的值
    lower = root.val;
    // 递归检查右子树,返回结果
    return checkValidBST(root.right);
}; 

时间复杂度 : O ( n ) O(n) O(n),其中 n n n 为二叉树的节点个数。二叉树的每个节点最多被访问一次。
空间复杂度 : O ( h ) O(h) O(h),其中 h h h 为二叉树的高度。递归最多有 h h h 层 / 栈最多存储 h h h 个节点。

非递归写法:

// javascript
var isValidBST = function(root) {
    const stack = [];
    let inorder = -Infinity;
    while (root !== null || stack.length > 0) {
    	// 存入当前节点 + 所有的左子节点
        while (root !== null) {
            stack.push(root);
            root = root.left;
        }
        root = stack.pop();
        // 如果中序遍历得到的节点的值小于等于前一个 inorder,说明不是二叉搜索树
        if (root.val <= inorder) {
            return false;
        }
        inorder = root.val;
        root = root.right;
    }
    return true;
};

解题二:传递最小与最大值

在这里插入图片描述

// javascript
var isValidBST = function(root) {
    // Number.MIN_VALUE: 5e-324
    // Number.MAX_VALUE: 1.7976931348623157e+308
    return checkValidBST(root, -Infinity, Infinity);
};

var checkValidBST = function(root, lower, upper) {
    if (root === null) return true;
    if (root.val <= lower || root.val >= upper) return false;
    return checkValidBST(root.left, lower, root.val) && checkValidBST(root.right, root.val, upper);
};

在这里插入图片描述

官方解答有动画演示:LeetCode 官方解答

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值