前言
相信很多人对于递归都有概念,但是在做题时想用递归时却发现用不好,或者说不知道参数设置,递归方法该写在哪里,这些都是递归相关基础知识不牢靠导致的。
本文为本人自学研究笔记,针对递归常见问题做出一些解释并研究,以求达到灵活运用。
总结:最里层的操作写在递归之前,最外面的操作写在递归之后。树肯定符合递归结构且是dfs。递归函数的参数定义取决于如何递归以及最终操作
比较经典的递归练习题:
1.二叉树最大深度(总结:最里层的操作写在递归之前,最外面的操作写在递归之后。树符合递归结构)
leetcode - 104
2.递归二叉树
什么是递归
看一个典型的问题斐波那契数列:
很明显这是符合递归定义的。
例如树的定义,也是递归。
递归的分类
递归虽然都叫递归,但是区别却很大。
向外递归
这是一种比较简单的递归,例如上方的斐波那契数列就是向外递归,这是因为我们的递归起点实际上是最里面一层(要先计算f(1)与f(0)才能知道后面的值),并逐步向外层函数传递数值,最终结果也由最外层函数返回,故将此类递归定义为向外递归。
特点:一定有返回值。
向内递归
有了向外递归的概念,理解向内递归就不是那么难了,很明显向内递归的递归起点实际上是最外面一层,并逐步向内层函数传递数值,最终结果也由最里层函数返回。
向内递归一定都是可以使用for循环实现的。
对于向内递归 一定要使用一个全局变量来表示结果。(如果只是方法变量会在方法结束后被释放)
public class Main {
static int a = 0 ;//标记结果的全局变量
public static void main(String[] args) {
digui(4);
System.out.println(a);
}
public static void digui(int target){
if(a == target) return;
a++;
digui(target);
}
}
特点返回值为void
让我们思考一个问题:递归的起点和终点是什么?
回答这个问题的答案显然有两个:一个对应向外递归,一个对应向内递归。
向外递归的终点与起点 与 递归方法的位置
我们将逻辑处理首先发生的位置称为起点,返回最终结果的位置称为终点。
这样向外递归的起点很明显在最内层的函数,要想达到这个效果,递归方法要写在所有逻辑处理代码之前。
说白了,向外递归适用于那些我们知道最里层,也就是最后一步的情形。
向内递归的终点与起点 与 递归方法的位置
同样我们将逻辑处理首先发生的位置称为起点,返回最终结果的位置称为终点。
这样向内递归的起点很明显在最外层的函数,要想达到这个效果,递归方法要写在所有逻辑处理代码之后。
很明显,向内递归类似于一个循环。
向内递归适用于那些我们知道最外层,也就是初始情况如何运算的情形。
向内递归相较于循环有什么优势?
从代码上看是没什么优势,建议直接循环