算法挑战55: 验证是否二叉搜索树

2 阅读1分钟

题目:

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

  • 节点的左子树只包含 严格小于 当前节点的数。
  • 节点的右子树只包含 严格大于 当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

思路:

什么是二叉搜索树?

就是每个节点的左子节点的值小于当前节点值,每个右子节点的值大于当前节点的值

我们有三种方式来实现

  • 前序
  • 中序
  • 后续

前序

先判断,再递归

利用边界来进行判断

中序

遍历一个,判断一下是否大于上一个节点的值

注意: 中序遍历二叉搜索树,得到的遍历结果是递增的

后续

代码:

前序:

var isValidBST = function (root) {
    function dfs(root, left , right ) { 
        if(!root)return true;
        let x = root.val;
        let leftVal = dfs(root.left,left,x);
        let rightVal = dfs(root.right,x,right);
        return left < x && x < right && leftVal && rightVal;
    }

    return dfs(root,-Infinity,Infinity);
};

中序:

var isValidBST = function (root) {
    let prev = -Infinity;
    function dfs(node) {
        if (!node) return true;

        let left = dfs(node.left);
        if (!left) return false;
        if (node.val <= prev) {
            return false;
        }
        prev = node.val;
        let right = dfs(node.right);
        return right;
    }
    return dfs(root);
};

后续:

感觉后续最麻烦

var isValidBST = function (root) {
    // 返回 [min, max] 或 null (如果不合法)
    function dfs(node) {
        if (!node) return [Infinity, -Infinity];

        const left = dfs(node.left);
        const right = dfs(node.right);

        // 如果左右子树有任何一个不合法(返回了 null),直接向上冒泡
        if (left === null || right === null) return null;

        const [leftMin, leftMax] = left;
        const [rightMin, rightMax] = right;

        // 检查当前节点是否合法
        if (leftMax >= node.val || rightMin <= node.val) {
            return null;
        }

        return [Math.min(node.val, leftMin), Math.max(node.val, rightMax)];
    }

    return dfs(root) !== null;
};