package class07;
/**
* 验证搜索二叉树
* <p>
* 另:判断是否是平衡搜索二叉树?
* 写两个函数,一个是判断是否是平衡二叉树,一个是判断是否是搜索二叉树。
* 将两个布尔值取与(即&&)的关系,就是最后结果。
*/
public class Code05_IsBinarySearchTree {
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode(int val) {
this.val = val;
}
}
/**
* 定义一个Info,包含三个信息:
* 是否是搜索树,当前树的最大值,当前树的最小值。
*/
public static class Info {
boolean isSearch;
int max;
int min;
public Info(boolean is, int ma, int mi) {
isSearch = is;
max = ma;
min = mi;
}
}
/**
* @param root 根节点
* @return 是否是搜索树
*/
public boolean isValidBST(TreeNode root) {
return process(root).isSearch;
}
public static Info process2(TreeNode x) {
//如果x是null,则返回null。也就是说,下游向上返回的Info,我们需要在上游判断这个Info是否为null。
if (x == null) {
return null;
}
Info leftInfo = process2(x.left);//x的左节点,递归去。最后返回leftInfo。
Info rightInfo = process2(x.right);//x的右节点,递归去。最后返回rightInfo。
int max = x.val;//先将最大值标记为x的值
int min = x.val;//先将最小值标记为x的值
if (leftInfo != null) {//如果leftInfo不为空
max = Math.max(leftInfo.max, max);//拿leftInfo的最大值和max比较,谁大,谁就是新的max。
min = Math.min(leftInfo.min, min);//拿leftInfo的最小值和min比较,谁小,谁就是新的min。
}
if (rightInfo != null) {//如果rightInfo不为空
max = Math.max(rightInfo.max, max);//拿rightInfo的最大值和max比较,谁大,谁就是新的max。
min = Math.min(rightInfo.min, min);//拿rightInfo的最小值和min比较,谁小,谁就是新的min。
}
//先定义当前树是搜索树。在后边的判断中,只要有一处违反了搜索树的要求,就将isSearch修改为false。
boolean isSearch = true;
if (leftInfo != null && !leftInfo.isSearch) {//如果leftInfo不是空,并且leftInfo不是搜索树
isSearch = false;//那么就将isSearch修改成false。
}
if (rightInfo != null && !rightInfo.isSearch) {//如果rightInfo不是空,并且rightInfo不是搜索树
isSearch = false;//那么就将isSearch修改成false。
}
//定义变量leftMaxLessX,即左树的最大值是否小于x的值。
//如果leftInfo是空,就返回leftMaxLessX是true。否则,就让leftInfo的最大值和x的值真实地比较一下。如果结果是小于,就返回true,否则返回false。
boolean leftMaxLessX = leftInfo == null ? true : (leftInfo.max < x.val);
//定义变量rightMinMoreX,即右树的最小值是否大于x的值。
//如果rightMinMoreX是空,就返回rightMinMoreX是true。否则,就让rightInfo的最小值和x的值真实地比较一下。如果结果是大于,就返回true,否则返回false。
boolean rightMinMoreX = rightInfo == null ? true : (rightInfo.min > x.val);
//if (!(leftMaxLessX && rightMinMoreX)) {//如果leftMaxLessX和rightMinMoreX并不都是true,那么整个树就不是搜索树。即将isSearch修改成false。
if (!leftMaxLessX || !rightMinMoreX) {//如果leftMaxLessX是false,或者rightMinMoreX是false,那么整个树就不是搜索树。即将isSearch修改成false。
isSearch = false;
}
return new Info(isSearch, max, min);//返回Info,包含三个信息。
//递归对每一个节点一视同仁,所以要构建一个包含三个信息的类(即Info)。你需要返回三个信息,我用哪个信息就调哪个信息,不用的就算了,但是你必须得返回这三个信息。
//否则,左子树的最大值要小于x的值,和右子树的最小值要大于x的值。这种非通用性的判断条件,会增加编写代码的难度。
}
public static Info process(TreeNode x) {
if (x == null) {
return null;
}
Info leftInfo = process(x.left);
Info rightInfo = process(x.right);
int max = x.val;
int min = x.val;
if (leftInfo != null) {
max = Math.max(leftInfo.max, max);
min = Math.min(leftInfo.min, min);
}
if (rightInfo != null) {
max = Math.max(rightInfo.max, max);
min = Math.min(rightInfo.min, min);
}
//先定义这个数不是搜索树,后边将搜索树的所有条件都列出来。只有符合所有的条件时,才将isSearch修改成true,否则维持false。
boolean isSearch = false;
//如果leftInfo是空,则不违反左子树是搜索树的要求。否则,返回leftInfo的真实情况。是搜索树就返回是;不是就返回不是。
boolean leftIsBST = leftInfo == null ? true : leftInfo.isSearch;
//如果rightInfo是空,则不违反右子树是搜索树的要求。否则,返回rightInfo的真实情况。是搜索树就返回是;不是就返回不是。
boolean rightIsBST = rightInfo == null ? true : rightInfo.isSearch;
boolean leftMaxLessX = leftInfo == null ? true : leftInfo.max < x.val;//同process()
boolean rightMinMoreX = rightInfo == null ? true : rightInfo.min > x.val;//同process()
if (leftIsBST && rightIsBST && leftMaxLessX && rightMinMoreX) {//只有这个4个条件同时满足时,才将isSearch修改成true。否则维持false。
isSearch = true;
}
return new Info(isSearch, max, min);
}
}