问题描述
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
节点的左子树只包含 小于 当前节点的数。
节点的右子树只包含 大于 当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
使用中序遍历解法
若某一棵树是二叉搜索树,则其中序遍历一定有序。所以利用这一个性质,再遍历左右子树的同时,直接查看该树是不是满足有序的条件。同时满足二叉树的条件需要满足左子树的最大值小于根节点的值,右子树的最小值大于根节点的值。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
long preValue = Long.MIN_VALUE;
/**
* 若二叉树是搜索二叉树,则中序遍历是有序的
* @param root
* @return
*/
public boolean isValidBST(TreeNode root) {
if (root == null) return true;
boolean isLeftBST = checkBST(root.left);
// 左子树是二叉搜索树时,需要判断左子树的最大值小于根节点的值,若大于时,返回false
if (!isLeftBST) return false;
if (root.val <= preValue) {
return false;
} else {
preValue = root.val;
}
// 判断右子树是不是搜索二叉树,此时不需要判断右子树的最小值大于根节点的值,因为preValue保证了一定满足
boolean isRightBST = checkBST(root.right);
return isRightBST;
}
/**
* 判断以root为根节点的树是不是二叉搜索树
* @param root
* @return
*/
private boolean checkBST(TreeNode root) {
if (root != null) {
Stack<TreeNode> stack = new Stack<>();
while (!stack.isEmpty() || root != null) {
if (root != null) {
stack.push(root);
root = root.left;
} else {
root = stack.pop();
// 处理弹出的节点
if (root.val <= preValue) { // 题目要求是节点的 左子树只包含 小于 当前节点的数。
return false;
} else {
preValue = root.val;
}
root = root.right;
}
}
}
return true;
}
}
递归套路解法(树形dp套路)
分析:
若以x为头节点的树是搜索二叉树,需要满足
左子树是二叉搜索树,右子树是二叉搜索树
左子树的最大值 < x.val, 右子树的最小值 > x.val
左右子树需要返回的信息是(是不是搜索二叉树,最小值,最大值 )
该方法的主要思路时假设根节点可以向其左右子树要答案。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
// 设计返回结构
class ReturnType{
boolean isBST;
long min;
long max;
public ReturnType(boolean isBST,long min,long max) {
this.isBST = isBST;
this.min = min;
this.max = max;
}
}
public boolean isValidBST(TreeNode root) {
return process(root).isBST;
}
private ReturnType process(TreeNode root) {
if (root == null) {
return null;
}
ReturnType leftReturn = process(root.left);
ReturnType rightReturn = process(root.right);
long min = root.val;
long max = root.val;
if (leftReturn != null) {
min = Math.min(min,leftReturn.min);
max = Math.max(max,leftReturn.max);
}
if (rightReturn != null) {
min = Math.min(min,rightReturn.min);
max = Math.max(max,rightReturn.max);
}
boolean isBST = true;
if (leftReturn != null && (leftReturn.isBST == false || leftReturn.max >= root.val)) {
isBST = false;
}
if (rightReturn != null && (rightReturn.isBST == false || rightReturn.min <= root.val)) {
isBST = false;
}
return new ReturnType(isBST,min,max);
}
}
结果:
递归套路:
中序遍历解法
总结: 测试用例好狗哦。