二叉树 是由结点组成的层次结构,每个结点最多有两个子结点:左子结点和右子结点。结点之间的关系形成了树的层次结构,其中最顶层的结点称为根结点。
这种简单灵活的结构使得二叉树在存储和操作数据时非常 高效 ,在计算机科学中被广泛应用,为许多算法和数据操作提供了强大的基础。
了解二叉树的小伙伴都知道,二叉树可以根据形态或数据的不同产生很多分类,包括 满二叉树 、完全二叉树 、平衡二叉树 、二叉树搜索树 等等。
满二叉树(Full Binary Tree): 所有层都被完全填充的二叉树,没有缺失的结点。满二叉树的结点数量是一个等比数列,结点总数为 ,其中 是树的高度。
完全二叉树(Complete Binary Tree): 完全二叉树是指除了最后一层外,所有层的结点都被完全填充,而且最后一层的结点都集中在左侧。不存在只含有右孩子而无左孩子的结点。
平衡二叉树(Balanced Binary Tree): 平衡二叉树是一种特殊的二叉树,其任意结点的左右子树高度差不超过1。这样的平衡性质确保在最坏情况下,树的高度不会太大,从而保持了检索和插入操作的高效性。
二叉搜索树(Binary Search Tree): 二叉搜索树是一种有序的二叉树。
1.结点 左子树 的值都 小于 该结点的值;
2.结点 右子树 的值都 大于 该结点的值;
3.任意结点的子树也都是二叉搜索树。
有序性质使得在 BST 中进行搜索、插入和删除等操作都具有高效的时间复杂度 。
那么给定一棵二叉树,如何判断 该树符合什么 类型 的二叉树呢?
下面进入本文的正题,用 一套递归逻辑 搞定二叉树的诸多题目!
// 二叉树的结构定义
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int value) {
this.value = value;
}
}
递归逻辑
二叉树本身就很 “递归”,因此我们就可以利用好递归的特性,解决一系列二叉树有关的题目。
分析当前结点需要哪些二叉树的信息才能完成条件判断,整合成一个结构体;
分别递归调用左右子树寻找该信息;
得到左右子树的信息后,思考怎样对该信息加工判断。
下面我们运用该逻辑对不同二叉树形态进行判断。
满二叉树
判断一棵二叉树是否为 满二叉树。
public static class Info {
public boolean isFull;
public int height;
public Info(boolean f, int h) {
isFull = f;
height = h;
}
}
public static boolean isFull(Node head) {
if (head == null) {
return true;
}
return process(head).isFull;
}
public static Info process(Node h) {
// base case
if (h == null) {
return new Info(true, 0);
}
Info leftInfo = process(h.left);
Info rightInfo = process(h.right);
boolean isFull = leftInfo.isFull && rightInfo.isFull && leftInfo.height == rightInfo.height;
int height = Math.max(leftInfo.height, rightInfo.height) + 1;
return new Info(isFull, height);
}
思路
若一棵树为满二叉树,则 左右子树 也均为 满二叉树 且左右满二叉树的 高度相同。因此,需要的信息就包括两个:
1.是否是满二叉树
2.树高
代码解释
首先定义结构体,包含布尔类型的 isFull 和整形 height 两个信息。
如果输入的 h 为空,认为空树也是一颗满二叉树,返回 true。
Info process(Node h) 函数进行主要判断:
- base case 是
h为空时,返回(true,0),表示这是 满二叉树 且高度为 0 ;
分别递归调用左右子树并记录信息。
- 如果左右子树均为满二叉树且高度相同,则
isFull设置为true。 height高度信息设置为左右子树的 最大值 + 当前结点的1高度。
最终返回isFull和height两个信息,函数传入根结点,返回根结点的isFull值即可:process(head).isFull。
平衡二叉树
判断一棵二叉树是否为 平衡二叉树。
public static class Info {
public boolean isBalanced;
public int height;
public Info(boolean i, int h) {
isBalanced = i;
height = h;
}
}
public static boolean isBalanced(Node head) {
if (head == null) {
return true;
}
return process(head).isBalanced;
}
public static Info process(Node h) {
if (h == null) {
return new Info(true, 0);
}
Info leftInfo = process(h.left);
Info rightInfo = process(h.right);
int height = Math.max(leftInfo.height, rightInfo.height) + 1;
boolean isBalanced = true;
if (!leftInfo.isBalanced || !rightInfo.isBalanced) {
isBalanced = false;
}
if (Math.abs(leftInfo.height - rightInfo.height) > 1) {
isBalanced = false;
}
return new Info(isBalanced, height);
}
思路
若一棵树为平衡二叉树,则 左右子树 也均为 平衡二叉树 且左右二叉子树的 高度之差不大于 1。因此,需要的信息就包括两个:
1.是否是平衡二叉树
2.树高
代码解释
首先定义结构体,包含布尔类型的 isBalanced 和整形 height 两个信息。
如果输入的 h 为空,认为空树也是一颗平衡二叉树,返回 true。
Info process(Node h) 函数进行主要判断:
- base case 是
h为空时,返回(true,0),表示这是 平衡二叉树 且高度为 0 ;
分别递归调用左右子树并记录信息。
height高度信息设置为左右子树的 最大值 + 当前结点的1高度。- 如果左右子树其中有一个 不是 平衡二叉树,整棵树不是平衡二叉树。
- 如果左右子树的高度差 > 1,则也说明整棵树不是平衡二叉树。
最终返回isBalanced和height两个信息,函数传入根结点,返回根结点的isBalanced值即可:process(head).isBalanced。
二叉搜索树
判断一棵二叉树是否为 二叉搜索树。
public static class Info {
public boolean isBST;
public int max;
public int min;
public Info(boolean i, int ma, int mi) {
isBST = i;
max = ma;
min = mi;
}
}
public static boolean isBST(Node head) {
if (head == null) {
return true;
}
return process(head).isBST;
}
public static Info process(Node h) {
if (h == null) {
return null;
}
Info leftInfo = process(h.left);
Info rightInfo = process(h.right);
int max = h.value;
if (leftInfo != null) {
max = Math.max(max, leftInfo.max);
}
if (rightInfo != null) {
max = Math.max(max, rightInfo.max);
}
int min = h.value;
if (leftInfo != null) {
min = Math.min(min, leftInfo.min);
}
if (rightInfo != null) {
min = Math.min(min, rightInfo.min);
}
boolean isBST = true;
if (leftInfo != null && !leftInfo.isBST) {
isBST = false;
}
if (rightInfo != null && !rightInfo.isBST) {
isBST = false;
}
if (leftInfo != null && leftInfo.max >= h.value) {
isBST = false;
}
if (rightInfo != null && rightInfo.min <= h.value) {
isBST = false;
}
return new Info(isBST, max, min);
}
思路
若一棵树为二叉搜索树,则 左右子树 也均为 二叉搜索树 ,且满足:
- 左子树的最大值 < 该结点的值
- 右子树的最小值 > 该结点的值
即:左 < 中 < 右 。因此,需要的信息就包括三个:
1.是否是二叉搜索树
2.最大值
3.最小值
代码解释
首先定义结构体,包含布尔类型的 isBST 和整形 max、min 三个信息。
Info process(Node h) 函数进行主要判断:
- base case 是
h为空时,返回null;
分别递归调用左右子树并记录信息。
- 最大最小值初始值设置为当前结点的值
h.value;如果左右子树存在,则分别比较并更新max和min值。 - 如果左右子树中任意一个不为空且 不是 二叉搜索树,则整棵树 不是 二叉搜索树。
- 如果左右子树的不满足“左 < 中 < 右”的要求,则也说明整棵树 不是 二叉搜索树。
最终返回isBST和max、min三个信息,函数传入根结点,返回根结点的isBST值即可:process(head).isBST。
总结
通过这三道题目的解答,相信小伙伴对二叉树的 递归套路 有了一定的认识。(套路太明显啦!)
下篇文章我们继续使用该 套路 解决二叉树的一些题目,并进行总结,帮助小伙伴直接拿下 二叉树!
~点赞 ~ 关注 ~ 不迷路 ~!!!
-------往期回顾-------