LeetCode热题(JS版) - 98. 验证二叉搜索树

64 阅读2分钟

题目

给定一个二叉树,判断其是否是一个有效的二叉搜索树。

假设一个二叉搜索树具有如下特征:

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

示例 1:

输入:
2
/ \
1   3
输出: true

示例 2:

输入:
    5
   / \
  1   4
     / \
    3   6
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。
     根节点的值为 5 ,但是其右子节点值为 4

思路

实现该算法的关键在于如何判断一棵二叉树是否是二叉搜索树。可以通过中序遍历的方式遍历整棵二叉树,并将遍历到的节点的值保存到一个数组中,然后判断该数组是否是升序排列的即可。

下面是 Typescript 的代码实现:

function isValidBST(root: TreeNode | null): boolean {
  let prev = -Infinity
  let isValid = true

  function inorder(node: TreeNode | null) {
    if (!node) {
      return
    }
    inorder(node.left)
    // 不满足从小到大的顺序
    if (node.val <= prev) {
      isValid = false
      return
    }
    prev = node.val
    inorder(node.right)
  }

  inorder(root)

  return isValid
}

首先,我们定义一个变量 prev,用于保存上一个遍历到的节点的值。初始值为负无穷大,因为二叉搜索树中的所有节点都应该大于负无穷大。

然后,我们定义一个变量 isValid,用于判断当前二叉树是否是二叉搜索树。初始值为 true。

接下来,我们定义一个名为 inorder 的递归函数,用于中序遍历整棵二叉树。在每个节点处,我们先递归遍历左子树,然后将当前节点的值与 prev 进行比较。如果当前节点的值小于等于 prev,则说明当前二叉树不是二叉搜索树,将 isValid 设置为 false 并返回。否则,我们将 prev 更新为当前节点的值,然后递归遍历右子树。

最后,我们调用 inorder 函数开始中序遍历整棵二叉树,并返回 isValid。

image.png

复杂度分析

  • 时间复杂度为 O(n)

对于每个节点而言,inorder 函数最多被调用一次,因此该算法的时间复杂度取决于遍历整棵二叉树所需的时间。由于每个节点最多只会被遍历一次,因此遍历整棵二叉树所需的时间是 O(n)。其中,n 是二叉树中节点的个数。

  • 空间复杂度为 O(n)

递归调用 inorder 函数所需的栈空间取决于递归栈的深度,而递归栈的深度又取决于二叉树的高度。在最坏情况下,二叉树的形态为一条链,递归栈的深度达到 n,因此空间复杂度为 O(n)。