题目:
给定一棵二叉树的head节点,返回这颗二叉树中最大的二叉搜索子树的大小。
一颗二叉树来讲,可能整棵树不是搜索二叉树,但子树是一颗搜索二叉树。如下图所示,这时要返回这颗子搜索二叉树的最大节点个数。下图中,最大的二叉搜索子树大小为:3(5 -> 1 -> 7)。
子树的概念是:每个单独节点算一棵子树, 5 -> 1 -> 7三个节点算一棵子树(不可以舍弃任何一个)
1 -> 5 -> 7 -> 6 -> 2同样也算一棵子树,同样不可以舍弃任何一个节点。
分析
- 如果左树是二叉搜索树的情况
- 右树是二叉搜索树的情况
- 整棵树是二叉搜索树的情况
- 判断是否是二叉搜索树需要左右子树max、min的值和当前值节点值进行比较,如果左树最大值小于当前值,右树最小值大于当前值,则说明是一颗二叉搜索树
- 需要整棵树的节点数变量(allSize)和满足子树最大二叉搜索树节点数变量(maxBSTSubtreeSize),如果两个值相等,说明是二叉搜索树,如果不相等,则说明不是(用这两个值在构建Info信息类时,可省略一个bollean isBST的变量)。
代码:
Info类用于收集树的信息,并通过递归返回给上层,供上层调用进行分析。
public static class Info{
int max;
int min;
int allSize;
//满足子树是二叉搜索树最大节点个数
int maxBSTSubtreeSize;
public Info(int maxBSTSubtreeSize,int allSize,int max,int min){
this.maxBSTSubtreeSize = maxBSTSubtreeSize;
this.allSize = allSize;
this.max = max;
this.min = min;
}
}
public static int largestBSTSubtree(Node head){
if(head == null){
return 0;
}
return process(head).maxBSTSubtreeSize;
}
// 6
// 2 7
// 1 5
public static Info process(Node head){
if (head == null){
return null;
}
Info leftInfo = process(head.left);
Info rightInfo = process(head.right);
int max = head.val;
int min = head.val;
int allSize = 1;
if (leftInfo != null){
max = Math.max(max,leftInfo.max);
min = Math.min(min,leftInfo.min);
allSize += leftInfo.allSize;
}
if (rightInfo != null){
max = Math.max(max,rightInfo.max);
min = Math.min(min,rightInfo.min);
allSize += rightInfo.allSize;
}
//如果左子树不为null,则修改 p1 为 左子树的最大二叉搜索树的个数
int p1 = -1;
if (leftInfo != null){
p1 = leftInfo.maxBSTSubtreeSize;
}
//如果右树不为null, 则修改 p2 为 右子树的最大二叉搜索树的个数
int p2 = -1;
if (rightInfo != null){
p2 = rightInfo.maxBSTSubtreeSize;
}
//只有在左右子树都满足是二叉搜索树的情况下,才更新p3。
int p3 = -1;
//左右子树的最大二叉搜索树的个数 = 左右子树整棵树的个数,则说明为二叉搜索树。
//如果maxBSTSubtreeSize != allSize 则说明之前遍历左右树过程中,出现了 左树最大值 > 当前节点 或 右树最小值 < 当前节点的情况
boolean isBSTLeft = leftInfo == null ? true : (leftInfo.maxBSTSubtreeSize == leftInfo.allSize);
boolean isSBTRight = rightInfo == null ? true : (rightInfo.maxBSTSubtreeSize == rightInfo.allSize);
if (isBSTLeft && isSBTRight){
//看左子树的最大值 是否小于当前树的值
//看右子树的最小值 是否小于当前数的值
boolean leftMaxLessX = leftInfo == null ? true : (leftInfo.max < head.val);
boolean rightMinMoreX = rightInfo == null ? true : (rightInfo.min > head.val);
if (leftMaxLessX && rightMinMoreX){
int leftSize = leftInfo == null ? 0 : leftInfo.allSize;
int rightSize = rightInfo == null ? 0 : rightInfo.allSize;
p3 = leftSize + rightSize + 1;
}
}
return new Info(Math.max(p3,Math.max(p1,p2)),allSize,max,min);
}