「这是我参与2022首次更文挑战的第34天,活动详情查看:2022首次更文挑战」。
一、二叉树中最大的搜索二叉树的大小
给定一棵二叉树的头节点head,返回这颗二叉树中最大的二叉搜索子树的大小
1、分析
一颗二叉树不一定就是搜索二叉树,但它的子树是二叉搜索树,求它的子树是二叉搜索树的大小
目标:x树上BST子树上的maxSize
x不做头:
- x左树上的maxBSTSize
- X右树上的maxBSTSize
x做头:x做头的maxBSTSize
- x左树是BST
- x右树是BST
- x左树的最大值 < x
- x右树的最小值 > x
- x左树size + x右树size + 1
如果maxBSTSize == size,则是BST,省掉BST变量
2、实现
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
public static class Info {
public int maxBSTSubtreeSize;
public int allSize;
public int max;
public int min;
public Info(int m, int a, int ma, int mi) {
maxBSTSubtreeSize = m;
allSize = a;
max = ma;
min = mi;
}
}
public static int maxSubBSTSize(Node head) {
if (head == null) {
return 0;
}
return process(head).maxBSTSubtreeSize;
}
private static Info process(Node x) {
if (x == null) {
return null;
}
Info leftInfo = process(x.left);
Info rightInfo = process(x.right);
int max = x.value;
int min = x.value;
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;
}
int p1 = -1; // 可能性一
if (leftInfo != null) {
p1 = Math.max(p1, leftInfo.maxBSTSubtreeSize);
}
int p2 = -1; // 可能性二
if (rightInfo != null) {
p2 = Math.max(p2, rightInfo.maxBSTSubtreeSize);
}
int p3 = -1; // 可能性三
boolean leftBST = leftInfo == null ? true : leftInfo.maxBSTSubtreeSize == leftInfo.allSize;
boolean rightBST = rightInfo == null ? true : rightInfo.maxBSTSubtreeSize == rightInfo.allSize;
if (leftBST && rightBST) {
boolean leftMaxLessX = leftInfo == null ? true : (leftInfo.max < x.value);
boolean rightMinMoreX = rightInfo == null ? true : (rightInfo.min > x.value);
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(p1, Math.max(p2, p3)), allSize, max, min);
}
二、二叉树中最大的二叉搜索树的头节点
给定一棵二叉树的头节点head,返回这颗二叉树中最大的二叉搜索子树的头节点
1、分析
x无关:
- x左树maxBSTNode
- x右树maxBSTNode
x有关:
- x左树max < x
- x右树min > x
- x是头节点,x.left == x左树的maxBSTNode && x.right == x右树的maxBSTNode
2、实现
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
public static class Info {
public Node maxSubBSTHead;
public int maxSubBSTSize;
public int min;
public int max;
public Info(Node h, int size, int mi, int ma) {
maxSubBSTHead = h;
maxSubBSTSize = size;
min = mi;
max = ma;
}
}
public static Node maxSubBSTHead(Node head) {
if (head == null) {
return null;
}
return process(head).maxSubBSTHead;
}
private static Info process(Node X) {
if (X == null) {
return null;
}
Info leftInfo = process(X.left);
Info rightInfo = process(X.right);
int min = X.value;
int max = X.value;
Node maxSubBSTHead = null;
int maxSubBSTSize = 0;
if (leftInfo != null) {
min = Math.min(min, leftInfo.min);
max = Math.max(max, leftInfo.max);
maxSubBSTHead = leftInfo.maxSubBSTHead;
maxSubBSTSize = leftInfo.maxSubBSTSize;
}
if (rightInfo != null) {
min = Math.min(min, rightInfo.min);
max = Math.max(max, rightInfo.max);
if (rightInfo.maxSubBSTSize > maxSubBSTSize) {
maxSubBSTHead = rightInfo.maxSubBSTHead;
maxSubBSTSize = rightInfo.maxSubBSTSize;
}
}
if ((leftInfo == null ? true : (leftInfo.maxSubBSTHead == X.left && leftInfo.max < X.value))
&& (rightInfo == null ? true : (rightInfo.maxSubBSTHead == X.right && rightInfo.min > X.value))) {
maxSubBSTHead = X;
maxSubBSTSize = (leftInfo == null ? 0 : leftInfo.maxSubBSTSize)
+ (rightInfo == null ? 0 : rightInfo.maxSubBSTSize) + 1;
}
return new Info(maxSubBSTHead, maxSubBSTSize, min, max);
}
三、返回二叉树中a和b的最低公共祖先
给定一棵二叉树的头节点head,和另外两个节点a和b。返回a和b的最低公共祖先
1、分析
最低公共祖先:一个节点往上跑,另一个节点也往上跑,它们在哪个节点汇聚问题
方法一:遍历每个节点的时候,把每个节点和它的父节点存入HashMap中,key:当前节点,value:当前节点的父节点。然后a节点往上走(从map中获取a的父节点),沿途把a这条线上的所有节点都放入Set中,然后b再往上一直走,如果b这条线上的某个节点存在Set中,则此时就是a和b的最低公共祖先
方法二:二叉树的递归套路
x无关:x不是最低汇聚点
- x的左树上有答案,a和b在x的左树上有汇聚点
- x的右树上有答案,a和b在x的右树上有汇聚点
- x整颗树上,a和b没找全
x有关:x是最低汇聚点
- x的左树发现了a和b其中一个,x的右树发现了a和b其中一个
- x本身就是a,x的左树或右树发现了b
- x本身就是b,x的左树或右树发现了a
信息收集:
这棵树上有没有发现a
这颗树上有没有发现b
这颗树上有没有发现a和b的汇聚点
2、实现
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
public static Node lowestAncestor(Node head, Node a, Node b) {
return process(head, a, b).ans;
}
private static Info process(Node x, Node a, Node b) {
if (x == null) {
return new Info(false, false, null);
}
Info leftInfo = process(x.left, a, b);
Info rightInfo = process(x.right, a, b);
boolean findA = (x == a) || leftInfo.findA || rightInfo.findA;
boolean findB = (x == b) || leftInfo.findB || rightInfo.findB;
Node ans = null;
if (leftInfo.ans != null) {
ans = leftInfo.ans;
} else if (rightInfo.ans != null) {
ans = rightInfo.ans;
} else {
if (findA && findB) {
ans = x;
}
}
return new Info(findA, findB, ans);
}