这道题与返回最大二叉搜索树的大小类似,都是收集并判断左右子树的信息。
- 递归的方式收集每个节点的信息,并拼装成info对象供上层调用。
- max用来判断左子树最大值是否小于当前节点,min用来判断右子树最小值是否大于当前节点,maxSubBSTSize 最大二叉搜索子树大小,maxSubBSTHead 最大二叉搜索子树的头结点。
- 一共三种情况,最大二叉搜索子树在左子树,最大二叉搜索子树在右子树和整棵树都为最大二叉搜索树。
- 如果整棵树都是二叉搜索树,则需要左子树的最大值 < 当前节点 < 右子树的最大值,并且左右子树的最大二叉搜索树的head节点,就是我当前节点的left、right节点。
递归方法
public static class Info {
int max;
int min;
Node maxSubBSTHead;
int maxSubBSTSize;
public Info(int max, int min, Node maxSubBSTHead, int maxSubBSTSize) {
this.max = max;
this.min = min;
this.maxSubBSTHead = maxSubBSTHead;
this.maxSubBSTSize = maxSubBSTSize;
}
}
public static Node maxSubBSTHead1(Node head) {
if (head == null) {
return head;
}
return process(head).maxSubBSTHead;
}
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;
Node maxSubBSTHead = null;
int maxSubBSTSize = 0;
if (leftInfo != null) {
max = Math.max(leftInfo.max, max);
min = Math.min(leftInfo.min, min);
maxSubBSTHead = leftInfo.maxSubBSTHead;
maxSubBSTSize = leftInfo.maxSubBSTSize;
}
if (rightInfo != null) {
max = Math.max(rightInfo.max, max);
min = Math.min(rightInfo.min, min);
//如果左右子树都不为null,用maxSubSBTSize变量判断哪个子树的头结点更大。
if (rightInfo.maxSubBSTSize > maxSubBSTSize) {
maxSubBSTHead = rightInfo.maxSubBSTHead;
maxSubBSTSize = rightInfo.maxSubBSTSize;
}
}
//第一次进来时,先等于当前节点
//如果 左数的最大二叉树头结点 是我当前节点的 left节点
//并且 右树的最大二叉树头节点 是我当前节点的 right 节点 则说明我的左右子树都是搜索二叉树
//那么 最大的搜索二叉树头节点,就等于我当前节点。
if ((leftInfo == null ? true : (leftInfo.maxSubBSTHead == head.left && leftInfo.max < head.val))
&& (rightInfo == null ? true : (rightInfo.maxSubBSTHead == head.right && rightInfo.min > head.val))) {
maxSubBSTHead = head;
maxSubBSTSize = (leftInfo == null ? 0 : leftInfo.maxSubBSTSize) + (rightInfo == null ? 0 : rightInfo.maxSubBSTSize) + 1;
}
return new Info(max, min, maxSubBSTHead, maxSubBSTSize);
}
暴力方式
中序遍历(左 -> 头 -> 右)的方式,遍历整棵二叉树,放到集合中,并遍历集合,如果整个集合元素都是由小到大的顺序,说明整棵树都是搜索二叉树,直接返回。
否则,递归遍历,找到最大的搜索二叉树。
public static Node maxSubBSTHead2(Node head) {
if (head == null) {
return head;
}
if (getMaxSize(head) != 0) {
return head;
}
Node left = maxSubBSTHead2(head.left);
Node right = maxSubBSTHead2(head.right);
return getMaxSize(left) >= getMaxSize(right) ? left : right;
}
public static int getMaxSize(Node head) {
if (head == null) {
return 0;
}
List<Node> list = new ArrayList<>();
in(head, list);
for (int i = 1; i < list.size(); i++) {
if (list.get(i).val <= list.get(i - 1).val) {
return 0;
}
}
return list.size();
}
public static void in(Node head, List<Node> list) {
if (head == null) {
return;
}
in(head.left, list);
list.add(head);
in(head.right, list);
}