98.验证二叉搜索树
给你一个二叉树的根节点 root
,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
- 节点的左子树只包含 小于 当前节点的数。
- 节点的右子树只包含 大于 当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
示例 1:
输入: root = [2,1,3]
输出: true
示例 2:
输入: root = [5,1,4,null,null,3,6]
输出: false
解释: 根节点的值是 5 ,但是右子节点的值是 4 。
提示:
- 树中节点数目范围在 [ 1 , 1 0 4 ] [1, 10^4] [1,104] 内
- − 2 31 ≤ N o d e . v a l ≤ 2 31 − 1 -2^{31} \leq Node.val \leq 2^{31} - 1 −231≤Node.val≤231−1
解法一(模拟+dfs)
思路分析:
- 利用二叉搜索树的性质,对树的节点进行检验
- 采用深度优先搜索进行遍历
实现代码如下:
class Solution {
public boolean isValidBST(TreeNode root) {
return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
private boolean isValidBST(TreeNode node, long minVal, long maxVal) {
if (node == null)
return true;
if (node.val <= minVal || node.val >= maxVal)
return false; // 该节点值 不满足二叉搜索树的范围 返回false
return isValidBST(node.left, minVal, node.val) && isValidBST(node.right, node.val, maxVal);
}
}
提交结果如下:
解答成功:
执行耗时:0 ms,击败了100.00% 的Java用户
内存消耗:42.1 MB,击败了88.95% 的Java用户
复杂度分析:
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( n ) O(n) O(n)
解法二(中序遍历+二叉搜索树性质)
思路分析:
- 根据二叉搜索树,节点左子树只包含小于当前节点的值, 节点右子树只包含大于当前节点的值,可以采用中序遍历;左中右的顺序,可以得到一个递增的有序数组
- 即判断中序遍历后的数组是否有序递增,即可检验该二叉树是否为二叉搜索树
- 同时,利用双指针,可以标记遍历前一个节点,然后进行比较,判断当前遍历节点值是否大于前一个节点值
- 大于,则符合二叉搜索树特点,继续遍历判断
- 小于,则不符合特点,返回false
实现代码如下:
class Solution {
// 中序遍历
TreeNode pre = null; // 标记中序遍历顺序当前节点的前一个节点
public boolean isValidBST(TreeNode root) {
if (root == null)
return true;
boolean left = isValidBST(root.left); // 中序遍历先 遍历判断左子树
if (pre != null && pre.val >= root.val) // 再判断中
return false; // 不符合条件
pre = root; // 更新指针
boolean right = isValidBST(root.right); // 中序遍历 遍历判断右子树
return left && right;
}
}
提交结果如下:
解答成功:
执行耗时:0 ms,击败了100.00% 的Java用户
内存消耗:42.3 MB,击败了70.75% 的Java用户
复杂度分析:
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( n ) O(n) O(n)