1 .递归的概念
一个方法在执行过程中调用自身, 就称为 “递归”.
递归相当于数学上的 “数学归纳法”, 有一个起始条件, 然后有一个递推公式.
使用 递归算法的 前提有两个:
(1) 原问题可以层层分解为类似的子问题,且子问题比原问题的规模更小。
(2)规模更小的子问题具有直接解
设计递归算法的原则是用自身的简单情况来定义自身设计递归算法的方法是:
(1)寻找分解方法,将原问题转化为子问题求解
(2)设计递归出口,也就是说根据最小的子问题,确定递归终止的条件。
2.递归求n的阶乘
public static void main(String[] args) {
int n = 5;
int ret = factor(n);
System.out.println("ret = " + ret);
}
public static int factor(int n) {
if (n == 1) {
return 1;
}
return n * factor(n - 1); // factor 调用函数自身
}
// 执行结果 ret = 120
递归执行过程分析
执行过程图
程序按照序号中标识的 (1) -> (8) 的顺序执行
3.斐波那契数列理解递归思想
第1.2项为1,以后的每一项都为 前两项之和:
1,1,2,3,5,8,13…
会让求第n项斐波那契数,
如何的到第n项呢?要是知道第n-1项和n-2就好了;
如何的到第n-1项呢?要是知道第n-2项和n-3就好;
…
如何的到第3项呢?要是知道第2项和1就好;
第2项和第1项我们知道啊(喏,我手上的黑萝卜给你!)
然后我们可以的到第3项,第4项…最后的到第n项
class Test {
public static void main(String[] args) {
System.out.println(fib(40));
}
public static int fib(int n) {
if (n == 1 || n == 2) {
return 1;
}
return fib(n - 1) + fib(n - 2);
}
}
// 执行结果 102334155
4.汉诺塔理解递归思想
有A,B,C三个竖杆,A上有上从下往上按照大小顺序摞着n个圆盘。将A上的圆盘按同样规则移动到C上,一次只能移动一个原配。求需要多少步,怎么移动?
这个问题咋一看特别复杂,用循环更是摸不着头脑。看看用递归是怎么解决的。
按递归的思想,要将n个A上的圆盘移动到C上,我们需要知道n-1个圆盘时是怎么移动.
知道后我们可以将n-1个圆盘先移动到B上,然后将A上最底下一个移动到C上,然后再用n-1个时方法将B上的n-1个圆盘移动到C上
可以的出第n项和n-1项的关系为f(n)=2*f(n-1)+1
最终就是我们只需要知道1个和2个圆盘时是怎么移动的,我们就解决这个问题。
if (n==1){ //一个圆盘时
System.out.println("A->C");
return count+=1;
}
if (n==2){ //两个圆盘时
System.out.println("A->B");
System.out.println("A->C");
System.out.println("B->C");
return count+=3;
}
然后加上前推条件
return 2*hannuo(n-1)+1;
完整的程序就能得到了
public static int hannuo(int n) {
int count=0; //计数
if(n<0){
System.out.println("输入错误");
}
if (n==1){ //一个圆盘时
// A->C
return count+=1;
}
if (n==2){ //两个圆盘时
// A->B
// A->C
// B->C
return count+=3;
}
return count+2*hannuo(n-1)+1;
}
5.递归小结
- 递归是一种重要的编程解决问题的方式. 有些问题天然就是使用递归方式定义的(例如斐波那契数列, 二叉树等), 此时使用递归来解就很容易。
- 有些问题使用递归和使用非递归(循环)都可以解决. 那么此时更推荐使用循环, 相比于递归, 非递归程序更加高效。
- 递归思想编程时最明显的特点就是代码少,且简单,同时它的缺点为占内存较大,计算速度慢。