「这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战」
验证二叉搜索树
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效二叉搜索树定义如下:
- 节点的左子树只包含 小于 当前节点的数。
- 节点的右子树只包含 大于 当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
解法
错误解法
这道题虽然不是很难,但很容易踩坑,我刚拿到这道题的时候,想的很简单,迭代的把每层的根节点和左子节点,右子节点做比较,不满足根节点val值大于左子节点val值,小于右子节点val值的返回false,迭代完还没有返回false则返回true。但是这样做很容易存在两个问题
- 每层虽然满足根节点val值大于左子节点val值,但左子节点那棵树中可以存在值大于根节点的值
- 每层虽然满足根节点val值小于右子节点val值,但右子节点那棵树中可以存在值小于根节点的值
递归正确解法
- 递归的参数和返回值:每次递归的参数是TreeNode节点,返回的是true和false,用以验证该层递归的子树是否符合搜索二叉树的特性
- 递归的终止条件:当递归传入的是空节点时,证明上一层递归是叶子结点,这层递归返回true
- 递归的单层逻辑:我们画出一个正常搜索二叉树,并写出它的中序遍历,可以发现,整个值是递增的,也就是按中序遍历防暑读取的节点val值,一定比前一个节点大,我们可以比较pre.val和root.val(当前遍历的节点值)并记录preNode,然后根据递归得到的左子树和右子树结果,返回true和false给上一层递归
// 递归解法
var isValidBST = function(root) {
let pre = null;
const inOrder = (root) => {
if (root === null)
return true;
let left = inOrder(root.left);
if (pre !== null && pre.val >= root.val)
return false;
pre = root;
let right = inOrder(root.right);
return left && right;
}
return inOrder(root);
};