题号:98
题目解读:
- 判断一棵二叉树是不是二叉搜索树。二叉搜索树需要满足:所有左子树上的节点的值小于当前节点的值,所有右子树上的节点的值小于当前节点的值。
- 陷阱1:只比较当前节点,和左右子节点的值 没有考虑整棵子树
1. 递归
时间:O(n) n是节点的个数
空间:O(n) n是栈空间的利用
核心思路是:
- 采用递归,退出条件 节点为null就返回true
- 每一层递归,当前节点的值要处于一个范围区间。如果是左节点,那么当前的root.val所处的区间是(-infinity, 当前节点的值),如果是右节点,(root.val, infinity)。注意是开区间,题目描述是“大于”“小于”
// 递归函数
const helper = (root, lower, upper) => {
// 1. 【递归的退出条件】当前节点是null 就返回true 为什么?因为叶子节点的话,可以不用比
if (root === null) {
return true
}
// 2. 【单层递归逻辑】如果越界 就return false
if (root.val < lower || root.val > upper) {
return false
}
// 3. 【递归点 传入参数 左右节点】
// 左节点递归【lower是 -Infinity upper是“当前节点” 因为后面的值都要比当前的值小 所以设置upper】
// 右节点递归【upper是 Infinity lower是当前节点 因为后的值都要比当前值大 所以设置lower】
return helper(root.left, -Infinity, root.val) && helper(root.right, root.val, Infinity)
}
// 主函数
var isValidBST = function (root) {
return helper(root, -Infinity, Infinity)
};
测试数据
function Node(val) {
this.val = val;
this.left = null;
this.right = null;
}
var a = new Node(6)
var b = new Node(4)
var c = new Node(8)
// var d = new Node(3)
// var e = new Node(4)
var f = new Node(7)
var g = new Node(2)
a.left = b
a.right = c
c.left = f
c.right = g
console.log(isValidBST(a));
2. 迭代
时间:O(n)
空间:O(n)
核心思路:1. 利用中序遍历的顺序,左中右 + 二叉搜索树的顺序 左小右大, 不断记录上一个节点的值,和当前节点进行比较。只要当前节点值小于上一个节点,就return false
var isValidBST = function (root) {
// 1. 初始化变量
// 栈数组
const stack = []
// 游标 current
let current = root
// 记录前一个节点
let pre = null
while (stack.length > 0 || current !== null) {
// 1. 中序遍历的套路 不断遍历 把游标的节点加入栈
if (current) {
stack.push(current)
// 2. 不断遍历左子树 节点 加入栈
current = current.left
} else {
// 3. 如果碰到了叶子节点 就取出栈的元素 判断值是否小于上一个节点的值
current = stack.pop()
// 4. 如果小于 证明不是二叉搜索树 因为二叉搜索树 左 - 中 - 右 应该是递增的顺序
if (pre !== null && current.val <= pre.val) {
return false
}
// 5. 修改上一个节点的值 为当前的节点
pre = current
// 6. 中序遍历的套路 修改游标
current = current.right
}
}
};
测试数据
function Node(val) {
this.val = val;
this.left = null;
this.right = null;
}
var a = new Node(6)
var b = new Node(4)
var c = new Node(8)
// var d = new Node(3)
// var e = new Node(4)
var f = new Node(7)
var g = new Node(2)
a.left = b
a.right = c
// b.left = d
// b.right = e
c.left = f
c.right = g
console.log(isValidBST(a));