注:本文的代码实现使用的是 JS(JavaScript),为前端中想使用JS练习算法和数据结构的小伙伴提供解题思路。
题目描述
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
- 节点的左子树只包含小于当前节点的数。
- 节点的右子树只包含大于当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
输入示例
输入:
2
/ \
1 3
输出: true
输入:
5
/ \
1 4
/ \
3 6
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。
根节点的值为 5 ,但是其右子节点值为 4 。
解题思路
1. 中序遍历法
根据二叉搜索树的性质,它的中序遍历后的结果一定是升序的,所以我们只需要判断中序遍历结果是否为升序即可。
var isValidBST = function(root) {
// 存储中序遍历后的结果
let nums = []
// 中序遍历函数
let inOrder = (root) => {
if(root === null) return
inOrder(root.left)
nums.push(root.val)
inOrder(root.right)
}
inOrder(root)
// 原始树为空,或只有一个节点,可以认为是二叉搜索树
if(nums.length <= 1) return true
// 在数组中,计算后一项减去前一项的差值,以判断是否升序
for(let i = 1, len = nums.length; i < len;i ++)
if(nums[i] - nums[i-1] <= 0) return false
return true
}
2. 递归法
我们可以使用纯递归的方法去遍历这棵树。所谓的二叉搜索树,就是左子树所有节点值均小于根节点的值,右子树所有节点值均大于根节点的值。因此,我们需要将所有左子树的上界和右子树的下界设置为根节点的值(不能相等);左子树的下界和右子树的上界继承根节点的下界和上界即可。
var isValidBST = function(root) {
let result = true
let check = (root, low, high) => {
if(root === null) return
// 若当前根节点的值超过了上界或下界,直接判定不是二叉搜索树
else if(root.val >= high || root.val <= low) return result = false
else{
// 检查左右子树
check(root.left, low, root.val)
check(root.right, root.val, high)
}
}
// 初始树的根节点没有上下界,因此分别设置为了负无穷和无穷大
check(root, -Infinity, Infinity)
return result
};
注意: 不能只比较当前节点值与左右子树节点值的大小,进行判别,以下是反例
5
/ \
1 4
/ \
3 6