98. 验证二叉搜索树
Tag Tree
DFS
Difficulty Medium
Link 98. 验证二叉搜索树
分析
二叉搜索树的特征是:
- 节点的左子树只包含小于当前节点的树
- 节点的右子树只包含大于当前节点的树
- 所有左子树和右子树自身也必须是二叉搜索树
比较容易想到深度优先搜索的方法,只要分别对左右子树深搜,同时判断大小。
但是要注意二叉搜索树的第三个条件,根节点的右子树的左儿子小于根节点的右儿子,如果它小于根节点,那么也不符合。即二叉搜索树应满足root.right.left.val<root.val
。但是如果只是按照左右子树深搜的话,不能够判断前面描述的情况。
所以,我们使用lower
和upper
在深搜时记录边界情况,如果在边界情况之外,则不符合二叉搜索树
题解
1. 递归
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isValidBST(TreeNode root) {
// 初始情况,根节点,没有最大最小的情况
return dfs(root, null, null);
}
private boolean dfs(TreeNode root, Integer lower, Integer upper) {
// 基准情况
if (root == null) return true;
int val = root.val;
if (lower != null && val <= lower) return false;
if (upper != null && val >= upper) return false;
// 左子树,当前节点的值为上界
if (!dfs(root.left, lower, val)) return false;
// 右子树,当前节点的值为下界
if (!dfs(root.right, val, upper)) return false;
return true;
}
}
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n) 遍历每一个节点
- 空间复杂度: O ( n ) O(n) O(n)
2. 中序遍历
中序遍历的顺序:左子树->根->右子树
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isValidBST(TreeNode root) {
return inorder(root);
}
private boolean inorder(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
// 测试用例里有一个整数最小值,这里如果用Integer,会判断错误
long border = Long.MIN_VALUE;
while (!stack.isEmpty() || root != null) {
// 对于每一个节点,不断取左子树
while (root != null) {
stack.push(root);
root = root.left;
}
// 先取出左儿子,然后取出父节点,最后是右儿子
root = stack.pop();
if (root.val <= border) return false;
border = root.val;
root = root.right;
}
return true;
}
}
复杂度分析
-
时间复杂度: O ( n ) O(n) O(n) 遍历每一个节点
-
空间复杂度: O ( n ) O(n) O(n)