给定一棵二叉树的头节点head,返回这颗二叉树中最大的二叉搜索子树的大小
思路
若当前不以x为头,那么看:
- x的左树中最大二叉搜索子树的大小
- x的右树中最大二叉搜索子树的大小
若当前节点为x为头,那么看经过x的树是不是二叉搜索树;
3. x的左子树是不是二叉搜索树
4. x的右子树是不是二叉搜索树
5. 左树的max < x
6. 右树的min > x
7. 左树的大小 + 右树的大小 + 1,就是当前二叉搜索子树的大小
代码实现
public class Code05_MaxSubBSTSize {
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
public static int maxSubBSTSize(Node head) {
if(head == null) {
return 0;
}
return process(head).maxBSTSubtreeSize;
}
public static class Info {
// 最大二叉搜索子树大小
public int maxBSTSubtreeSize;
// 当前树大小
public int allSize;
// 当前树最大值
public int max;
// 当前数最小值
public int min;
public Info(int maxBSTSubtreeSize, int allSize, int max, int min) {
this.maxBSTSubtreeSize = maxBSTSubtreeSize;
this.allSize = allSize;
this.max = max;
this.min = min;
}
}
private static Info process(Node head) {
if (head == null) {
return null;
}
// 收集左树右树信息
Info leftInfo = process(head.left);
Info rightInfo = process(head.right);
int allSize = 1;
int max = head.value;
int min = head.value;
// 判断左右树为不为空,若不为空,则更新max,min,allSize
if (leftInfo != null) {
max = Math.max(leftInfo.max, max);
min = Math.min(leftInfo.min, min);
allSize += leftInfo.allSize;
}
if (rightInfo != null) {
max = Math.max(rightInfo.max, max);
min = Math.min(rightInfo.min, min);
allSize += rightInfo.allSize;
}
int p1 = -1; // 单独左树中最大搜索子树的大小
if (leftInfo != null) {
p1 = leftInfo.maxBSTSubtreeSize;
}
int p2 = -1; // 单独右树中最大搜索子树的大小
if (rightInfo != null) {
p2 = rightInfo.maxBSTSubtreeSize;
}
int p3 = -1; // 包含当前head的最大搜索子树的大小,即左右连起来
// 首先判断左右子树是不是二叉搜索树,即对应子树的maxBSTSubtreeSize是否等于allSize
boolean leftBST = leftInfo == null ? true : (leftInfo.maxBSTSubtreeSize == leftInfo.allSize);
boolean rightBST = rightInfo == null ? true : (rightInfo.maxBSTSubtreeSize == rightInfo.allSize);
// 如果左右子树都是二叉搜索子树,则连起来
if (leftBST && rightBST) {
// 判断左子树最大值是否小于当前根节点值
boolean leftMaxLessHead = leftInfo == null ? true : (leftInfo.max < head.value);
// 判断右子树最小值是否大于当前根节点值
boolean rightMinMoreHead = rightInfo == null ? true : (rightInfo.min > head.value);
// 如果均满足上述所有条件,才能够连接
if (leftMaxLessHead && rightMinMoreHead) {
int leftSize = leftInfo == null ? 0 : leftInfo.allSize;
int rightSize = rightInfo == null ? 0 : rightInfo.allSize;
p3 = leftSize + rightSize + 1;
}
}
// 比较单独左树,单独右树,以及左右连接后最大二叉搜索子树的大小,返回最大的
int maxBSTSubtreeSize = Math.max(p1, Math.max(p2, p3));
return new Info(maxBSTSubtreeSize, allSize, max, min);
}
}