98. 验证二叉搜索树
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
(1)节点的左子树只包含小于当前节点的数。
(2)节点的右子树只包含大于当前节点的数。
(3)所有左子树和右子树自身必须也是二叉搜索树。
示例 1:
示例 2:
(来源:力扣(LeetCode))
思路:
由二叉搜索树的特征可得:
(1) 若它的左子树不空,则 左子树 上所有结点的值 均小于它的根结点的值;
(2) 若它的右子树不空,则 右子树 上所有结点的值 均大于它的根结点的值;
(3) 它的 左、右子树又分别为二叉排序树 。
所以我们使用中序遍历,遍历顺序为根结点—左子树—右子树,这样得到的得到的序列一定是升序的。
因此我们只要检查当前节点的值是否大于前一个中序遍历到的节点的值即可。如果均大于说明这个序列是升序的,整棵树是二叉搜索树,否则不是,
class Solution {
long pre = Long.MIN_VALUE;//用一个比树中所有节点可能的值都小的值去初始化pre
public boolean isValidBST(TreeNode root) {
if(root == null) {
return true;
}
if(!isValidBST(root.left)) {//访问左子树,如果左子树不满足二叉搜索树,直接返回false。
return false;
}
if(root.val <= pre) {// 访问当前节点,如果当前节点小于等于中序遍历的前一个节点,说明不满足BST,返回 false;否则继续遍历。
return false;
}
pre = root.val;
return isValidBST(root.right);//访问右子树
}
}
递归方法:
我们设计一个递归函数traverse(root, min, max)来判断子树中所有节点的值是否都在 (min,max) 的范围内,如果 root 节点的值不在 (min,max) 的范围内说明不满足条件直接返回,否则我们要继续递归调用检查它的左右子树是否满足,如果都满足才说明这是一棵二叉搜索树。
根据二叉树性质,在递归调用左子树时,我们需要把上界 max 改为 root.val,即调用 traverse(root.left, min, root.val),因为左子树里所有节点的值均小于它的根节点的值。同理递归调用右子树时,我们需要把下界 min改为 root.val,即调用 traverse(root.right, root.val, max))。
class Solution {
public boolean isValidBST(TreeNode root) {
return traverse(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
public boolean traverse(TreeNode node, long min, long max) {
if(node == null) {
return true;
}
if(node.val <= min || node.val >= max) {
return false;
}
if(!traverse(node.left, min, node.val)) {
return false;
}
if(!traverse(node.right, node.val, max)) {
return false;
}
return true;
}
}