什么是搜索二叉树
二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。二叉搜索树作为一种经典的数据结构,它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势;所以应用十分广泛,例如在文件系统和数据库系统一般会采用这种数据结构进行高效率的排序与检索操作。
题目描述
给定一棵二叉树的头节点head,返回这颗二叉树中最大的二叉搜索子树的头节点
如果这颗二叉树整体是二叉树,就计算出所有节点数,如果不是,就去查找有没有符合搜索二叉树条件的子树.然后找出节点数最多的子树,返回节点个数.
递归解法一
1.先定义出二叉树
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int value) {
val = value;
}
}
- 解题思路
递归调用每个子树时,判断是不是搜索二叉树,并且比较左树和右树,哪个搜索子树的节点比较多,返回节点数量值.
3.上代码
/**
* 二叉树的中序遍历,形成左右头的顺序放在集合中,根据搜索二叉树的特点.
* 头节点大于左边节点小于右边节点 就可以判断当前树是否符合是搜索二叉树
* @param head
* @param nodes
*/
public static void in(TreeNode head, List<TreeNode> nodes){
if (head == null){
return;
}
in(head.left,nodes);
nodes.add(head);
in(head.right,nodes);
}
/**
* 计算如果符合搜索二叉树,返回二叉树的节点数
* @param head
* @return
*/
public static int getBSTSize(TreeNode head){
if (head == null){
return 0;
}
ArrayList<TreeNode> nodes = new ArrayList<>();
in(head,nodes);
//判断是否满足搜索二叉树,不满足的话返回0
for (int i = 1; i < nodes.size();i++){
if (nodes.get(i).val <= nodes.get(i - 1).val){
return 0;
}
}
return nodes.size();
}
/**
* 递归计算最大节点数
* @param head
* @return
*/
public static int getMaxBSTSize(TreeNode head){
//base case 1 ,为null 返回0
if (head == null){
return 0;
}
//当前树如果是搜索二叉树,就不需要向下递归了,所以也可以返回
int size = getBSTSize(head);
if (size != 0){
return size;
}
//比较返回最大值
return Math.max(getMaxBSTSize(head.left),getMaxBSTSize(head.right));
}
递归解法二
1.解题思路
我们递归时,在每颗子树上去生成四个信息,当前子树的总节点数,最大值最小值,和最大二叉搜索子树的节点数.
为什么要这四个值,
1.拿到做大值和最小值,方便我们判断左树和右树是不是合在一起也满足搜索二叉树,因为搜索二叉树上头节点上的值大于左树最大值,小于右树最小值.
2.拿到所有节点数和最大搜索二叉子树的节点数,为了判断两者相等不,如果相等,说明当前树整棵是搜索二叉树.
2.直接上代码.
/**
* 构建消息体
*/
public static class Info{
//所有节点数
int allSize;
//二叉搜索子树的节点数
int maxSubSize;
//最大值
int max;
//最小值
int min;
public Info(int allSize, int maxSubSize, int max, int min) {
this.allSize = allSize;
this.maxSubSize = maxSubSize;
this.max = max;
this.min = min;
}
}
/**
* 递归调用过程
* @param head
* @return
*/
public static Info process(TreeNode head){
//base case 因为最大值和最小值无法构建,所以返回null.底下构建消息时,再处理null 的问题
if (head == null){
return null;
}
Info left = process(head.left);
Info right = process(head.right);
int max = head.val;
int min = head.val;
//allSize 头节点本身是1
int allSize = 1;
if (left != null ){
max = Math.max(max,left.max);
min = Math.min(min,left.min);
allSize += left.allSize;
}
if (right != null ){
max = Math.max(max,right.max);
min = Math.min(min,right.min);
allSize += right.allSize;
}
//左树最大搜索二叉树的个数
int p1 = 0;
if (left != null){
p1 = left.maxSubSize;;
}
//右树最大搜索二叉树的个数
int p2 = 0;
if (right != null){
p2 = right.maxSubSize;
}
int p3 = 0;
boolean leftBST = left == null ? true : (left.allSize == left.maxSubSize);
boolean rightBST = right == null ? true : (right.allSize == right.maxSubSize);
if (leftBST && rightBST){
p3 = left == null ? 0 : left.maxSubSize +
(right == null ? 0 : right.allSize) + 1;
}
return new Info(allSize,Math.max(Math.max(p1,p2),p3),max,min);
}
/**
* 主方法调用
* @param head
* @return
*/
public static int getMaxSUBSTSize(TreeNode head){
if (head == null){
return 0;
}
return process(head).maxSubSize;
}