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 官方解答