一、重要说明
1、递归是一种思想,将这种思想落实到二叉树这种数据结果的相关运用上,使我更加了解递归的作用。
2、以下所举的算法例子主要都是基于后序遍历的基础上实现的,即先遍历左子树,再遍历右子树,最后访问根节点,对于每一棵树都是如此。可以认为,递归方式可以从左/右子树上收集信息,从而在根节点处进行汇总。
3、递归分为在递去的过程中解决问题以及在归来的过程中解决问题。因为我想要的信息是从底层往上给(可以是叶子节点,也可以是空节点-》结束/返回条件),所以是在归来的过程中解决问题。
4、方法论:(可以指导对问题的思考,分析如何解决问题)
(1)假设以X节点为头,假设可以向X左树和X右树要任何信息
(2)在上一步假设下,讨论以X为头结点的树,得到答案的可能性(一般分类:与X有关、与X无关)
(3)列出所有可能性后,确定到底需要向左树和右树要什么样的信息
(4)把左树信息和右树信息求全集,就是任何一棵子树都需要返回的信息S
(5)递归函数都返回S,每一棵子树都这么要求
(6)写代码时,在代码中考虑如何把左树的信息和右树的信息整合出整棵树的信息(目标是加工出信息,也就是为Info中的每一个属性进行赋值)
5、一般需要思考的问题
(1)递归一定有一个返回机制,可以在叶子节点返回(例4),可以在null处返回,需要给出其对应的返回值,如果返回值中有要素不好确定,可以直接返回null,故而后续使用中需要进行非空判断(例3)。
(2)设定改变变量的机制,会增强设计的便利性(例3),即以假定一个初始值,然后满足if的条件,即可改变变量值(分解的思想)
(3)与X有/无关的说法是为了分析问题出现的情况,真正实现的时候其实不知道有没有关,结果是需要决策出来的。
二、Examples
1、判断一棵二叉树是否是平衡树
分析:
1、假设我们需要判断的树是以X为头结点的树,分类标准其实就是与X有关,与X无关。
与X有关即,左树和右树各自平衡,需要在X处对左树与右树的高度差进行判断(高度差不能大于1)。
与X无关,即左树或者右树已经出现不平衡性,故而不需要再在X处进行判断了。
代码实现的时候不要基于与X有无关,而是基于要为返回信息赋值,怎样的情况赋怎样的值。
2、整理出应返回的信息有:子树高度、子树的平衡性。
public static class Info{
public int height;
public boolean isBalance;
public Info(int height,boolean isBalance) {
this.height = height;
this.isBalance = isBalance;
}
}
算法实现:
public static Info process(Node head) {
if(head == null) {
//返回条件,如果子树为空
return new Info(0,true);//高度为0,且是平衡
}
Info leftInfo = process(head.left);//收集左树信息
Info rightInfo = process(head.right);//收集右树信息
//开始整合出该节点需要返回的信息
int height = 0;//设置初始高度为1
boolean isBalance = false;//设置是不平衡,后面如果满足平衡的条件则改为true
height = Math.max(leftInfo.height, rightInfo.height) + 1;
if(leftInfo.isBalance
&& rightInfo.isBalance
&& Math.abs(leftInfo.height - rightInfo.height) <= 1) {
isBalance =