目录
1.判断二叉树是否对称或相同
统一思路
- 成对的比较树的节点
- 判断对称时,成对地比较外侧节点。
- 判断相同时,成对地比较同侧地节点。
遍历顺序
- 判断对称时,左子树遍历顺序为左右中,右子树遍历顺序为右左中。
- 判断相同时,左右树遍历顺序相同,都为左右中。
递归和迭代
- 递归法:再递归函数中编写判断逻辑,每次递归都要判断当前子树是否对称或相同。
- 迭代法:使用容器,每次存储一对要比较的节点,取出节点比较的同时,把这两个节点的子节点成对地存储进容器中。
2.求二叉树的最大深度
题目解读
求二叉树的最大深度就是求根节点的最大高度,也就是求离根节点距离最远的叶子节点的距离。
递归法逻辑
- 使用前序遍历来遍历整棵树:中左右
- 当节点的左右子节点都为空时,表明到达了叶子节点,执行返回操作
- 深度的记录:使用
result
变量记录整棵树的最大深度,用depth
记录递归过程中的深度变化;只有当depth
变化到大于result
的时候再改变result
的值。
迭代法逻辑
- 使用层序遍历来遍历整棵树
- 进行每一层遍历的时候深度
depth
加一,最终的depth
的值就是二叉树的最大深度。
3.求二叉树的最小深度
题目解读
求二叉树的最小深度,就是求离根节点最近的叶子节点的距离。
递归法逻辑
- 总思路:二叉树的最小深度 = 根节点深度1 + 左右子树中的最小深度
- 用后序遍历来遍历整棵树:左右中
- 求深度的逻辑:
- 如果当前节点为空,则不增加深度,返回0;
- 如果当前节点有左子节点无右子节点,则以当前节点为根节点的子树最小深度 = 当前节点深度1 + 左子树最小高度
- 如果当前节点有右子节点无左子节点,则以当前节点为根节点的子树最小深度 = 当前节点深度1 + 右子树最小高度
- 如果当前节点有左子节点和右子节点,则以当前节点为根节点的子树的最小深度 = 当前节点深度1 + min(左子树高度, 右子树高度)
遍历法逻辑
- 使用层序遍历
- 每遍历一层节点,深度加一
- 如果遇到有节点无左右子节点,直接将当前深度返回,当前深度就是二叉树的最小深度
4.求二叉树的节点数
递归法
- 使用前中后序遍历皆可。
- 当前节点为空时,代表没有遍历到新节点,返回0。
- 当前节点不为空时,代表遍历到了新节点,就可以把当前节点计入二叉树节点数,节点数+1。(也就是每次遍历到新的节点的时候,把节点数加1)
- 针对不同的遍历方式,设置不同的递归逻辑。
迭代法
- 以层序遍历解决。(深度优先遍历也可以)
- 在遍历的过程中,每遍历一层时,得出这一层的节点个数,然后将每一层的节点个数加在一起。
5.判断二叉树是否是平衡二叉树
题目解读
要判断二叉树是否为平衡二叉树,重点在于判断每一个节点的左子树高度和右子树高度的差的绝对值不大于1
递归法
- 根据题目解读,来设计一个可以求出以当前节点为根节点的二叉树的高度的递归函数。在递归函数内求出左子树和右子树的高度,并计算它们高度差的绝对值。
- 递归逻辑:
- 如果当前节点为空,代表二叉树高度为0,返回0;
- 后序遍历,左右中:先求左子树的高度,再求右子树的高度,再处理中间节点。
- 处理中间节点:每次递归完成,以中间节点为根节点的二叉树高度 = 中间节点1 + max(左子树高度,右子树高度),再将这个高度返回。
ps:二叉树的高度 = 根节点1 + 左右子树中的最大高度
迭代法
- 设计一个函数,可以求出以参数cur节点为根节点的子树的高度。
- 主函数:用栈模拟后序遍历,每遍历到一个节点,算出它的左子树高度和右子树高度,并把它们的高度差和1作比较,如果大于1,则表明这个树不是平衡二叉树,返回false;否则,返回true。
6.求二叉树的所有路径
递归法
- 重要参数选择说明:
path
用来存储遍历过程中的一条路径、result
用来存储二叉树中所有合法的路径 - 递归逻辑:使用任意一种深度优先遍历技术对二叉树进行遍历(这里用前序遍历)
- 每遍历完一条完整的路径,也就是遇到叶子节点,就遍历
path
中的值,转换成路径的表达方式加到result
里 - 递归过程中的回溯 :每次递归结束,从上一个节点返回,
path
中保存的上一个节点也应弹出,这是一次显性的回溯操作(事实上,只要有递归就有回溯)。 - 递归函数功能说明:遍历整个二叉树,并把所有合法的路径加入结果集中。
迭代法
- 使用一个栈
st1
模拟递归来遍历二叉树,使用另一个栈st2
来存储遍历过程中的所有路径。 - 当遇到叶子节点的时候
st2
栈顶存储的路径就是一条完整的合法路径。 - 每当从
st1
栈中取出一个节点遍历的时候,总从st2
中取出对应的路径来进行回溯操作。 - 如果取出的这个节点是叶子节点,就把取出的相应的路径加入结果集。
总结
- 深度和高度
- 节点深度:根节点到当前节点的节点个数
- 节点高度:叶子节点到当前节点的节点个数
- 二叉树的最大深度 :根节点到离它最远的叶子节点的节点个数,其实就是二叉树的高度
- 二叉树的最小深度:根节点到离它最近的叶子节点的节点个数
- "求深度和高度的题目" ==> "求最小深度和最大深度(高度)的题目",题目中让求二叉树(最大/小)深度的问题完全可以转化为求(特定)高度的问题,都可以用遍历的方法加上条件判断语句解决。
有用的概念
:节点深度、二叉树高度、二叉树最大深度、二叉树最大高度 节点高度(除外)
- 遍历技术如何求深度和高度
- 层序遍历:遍历过程中,每遍历一层,当前节点深度加一,已知二叉树高度加一。(节点的高度再题目中好像并没有多少实际意义)
- DFS:每向子节点前进一次,相应的节点深度和已知二叉树高度加一、回退时相应深度减一
- DFS的实现
- 递归实现:参数、返回值、终止条件、递归逻辑(前中后)的设计,再题目中使用时往往要注意中间节点代码处理的逻辑
- 迭代实现:借用栈,根据遍历顺序的不同来编写把节点压入和取出栈的逻辑。先要压入栈,然后从栈中取出才能加入结果集,把节点从栈中取出加入结果集的同时把节点的子节点按照顺序压入栈中。
- BFS的实现
- 递归实现:给递归函数设计一个深度参数,再递归过程中,根据深度参数来把节点放入指定的层数;结果集是一个二维数组,二维数组的每一行代表一层。(可见递归函数中参数设计的重要性)
- 迭代实现:借用队列实现,先把节点加入队列,然后从队列取出放入结果集,同时,把这个节点的子节点从左到右的加入队列。
- 递归函数的设计
递归函数设计的重中之重是:
先明确递归函数的功能然后去实现
、递归三部曲
.