题目
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
- 节点的左子树只包含小于当前节点的数。
- 节点的右子树只包含大于当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
示例1:
输入:
2
/ \
1 3
输出:true
示例2:
输入:
5
/ \
1 4
/ \
3 6
输出:false
解释:输入为: [5,1,4,null,null,3,6]。
根节点的值为 5 ,但是其右子节点值为 4 。
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。
根节点的值为 5 ,但是其右子节点值为 4 。
思路:
**
方法1:
二叉搜索树的特性大家都知道,左边的小于根,右边的大于根,一开始就想一个递归就结束了,但是没想到隔层之间也需要大小值的比较。
例如:
20
/ \
10 30
\
25
这个返回的是true,但显然不是二叉搜索树。
最后参考了别人的代码,添加了一个最大最小值,来限定每个节点的有效取值范围。假设任一根节点root的取值范围为(min,max),则左子女的取值范围为(min,root.val),右子女的取值范围是(root.val,max),依次执行下去,一旦检测到节点值不在这个范围则返回 false。真是太机智了。还有就是在传输过程中原函数不能够传递最大最小值,又重新定义了一个函数调用,值得学习。
public boolean isValidBST(TreeNode root) {
return subTree(root,Long.MIN_VALUE,Long.MAX_VALUE);
}
public boolean subTree(TreeNode root,long min,long max){
if(root == null){
return true;
}
if(root.val<max&&root.val>min
&&subTree(root.left,min,root.val)
&&subTree(root.right,root.val,max)) {
return true;
} else {
return false ;
}
}
方法2:二叉搜索树的中序遍历结果是一个严格递增的序列,利用这一约束条件也可以判断是否是二叉搜索树。
class Solution {
long last = Long.MIN_VALUE;
public boolean isValidBST(TreeNode root) {
return inOrder(root);
}
public boolean inOrder(TreeNode root){
if(root!=null){
if(inOrder(root.left)==false) return false;
if(root.val<=last) return false;
last = root.val;
if(inOrder(root.right)==false) return false;
}
return true;
}
}
总结:
以上两种方法的时间复杂度都是O(n),递归的空间复杂度也都是O(logn)。
参考链接:c++版