Shu-How Zの小窝

Loading...

[面试题 04.05. 合法二叉搜索树](https://leetcode.cn/problems/legal-binary-search-tree-lcci/)

class TreeNode {
  constructor(val, left = null, right = null) {
    this.val = val;
    this.left = left;
    this.right = right;
  }
}

var isValidBST = function (root) {
  let stack = [];
  let inorder = -Infinity;
  while (stack.length || root) {
    while (root) {
      stack.push(root);
      root = root.left;
    }
    root = stack.pop();
    if (root.val <= inorder) return false;
    inorder = root.val;
    root = root.right;
  }
  return true;
};

// 构建测试用例
let root1 = new TreeNode(2, new TreeNode(1), new TreeNode(3));
console.log(isValidBST(root1)); // 输出: true

let root2 = new TreeNode(
  5,
  new TreeNode(1),
  new TreeNode(4, new TreeNode(3), new TreeNode(6))
);
console.log(isValidBST(root2)); // 输出: false

这段代码实现了一个函数 isValidBST,用于判断一棵二叉树是否为有效的二叉搜索树(Binary Search Tree, BST)。下面是对代码的详细分析:

代码逻辑

  1. 初始化

    • stack:一个栈,用于辅助中序遍历。
    • inorder:记录上一次访问的节点值,初始值为负无穷大 -Infinity
  2. 外层循环

    • 条件是 stack.length || root,即只要栈不为空或者当前节点不为空,就继续执行。
  3. 内层循环

    • 将当前节点的所有左子节点依次入栈,直到到达最左边的节点。
    • 这一步模拟了递归调用时不断深入到左子树的过程。
  4. 处理中间节点

    • 弹出栈顶元素,即当前子树中最左边的节点。
    • 检查该节点的值是否大于 inorder。如果不是,则说明不是有效的二叉搜索树,返回 false
    • 更新 inorder 为当前节点的值。
    • 处理完当前节点后,转向其右子节点,开始对右子树进行同样的操作。
  5. 返回结果

    • 如果整个遍历过程中没有发现违反二叉搜索树性质的情况,则返回 true

时间复杂度

  • 由于每个节点都被访问一次,因此时间复杂度为 O(n),其中 n 是树中节点的数量。

空间复杂度

  • 最坏情况下(当树退化成链表时),空间复杂度为 O(n)。平均情况下,空间复杂度为 O(h),其中 h 是树的高度。

示例

假设有一棵如下所示的二叉树:

    2
   / \
  1   3

调用 isValidBST(root) 将返回 true,因为这是一棵有效的二叉搜索树。

而如果树变为:

    5
   / \
  1   4
     / \
    3   6

调用 isValidBST(root) 将返回 false,因为节点 4 的左子节点 3 不满足小于 4 的条件。

完整代码示例

为了更好地理解,这里提供一个完整的可运行的代码示例,包括构建二叉树和测试 isValidBST 函数的功能。

这个示例不仅包含了 isValidBST 函数的实现,还提供了如何构建二叉树以及如何测试该函数的方法。通过运行这些代码,可以验证 isValidBST 函数的正确性。

posted @ 2024-11-23 21:50  KooTeam  阅读(24)  评论(0)    收藏  举报