1. 什么是递归
程序调用自身的编程技巧称为递归。
一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法。
2. 递归问题的特点
(1)一个问题可被分解为若干层简单的子问题。
(2)子问题和其上层问题的解决方案一致。
(3)外层问题的解决依赖于子问题的解决。
递归结构包括两个部分:
递归结束条件。解答:什么时候不调用自身方法。如果没有条件,将陷入死循环。
递归体。解答:什么时候需要调用自身方法。
例:案例:使用递归求n!
/**
* 功能:not 1+2+3....+100=?
but 1*2*3*4*5......*n=?
技能:递归
解决方式1:采用循环 6!=1*2*3*4*5*6
解决方式2:采用递归 6!=6*5! 5!=5*4! 4!=4*3! 3!= 3*2! 2!=2*1! 1!=1
*
* @豆皮没有豆
*/
public class YuFa40 {
public static void main(String[] args) {
long result = 1;
int n = 6;
//方式1:循环
for(int i=1;i<=n;i++){
result = result * i;
}
System.out.println(n+"!="+result);
//方式2:递归
long result2 = fac(n);
System.out.println(n+"!="+result2);
}
/*
求阶乘
n:
返回值:阶乘的结果
*/
public static long fac(int n){
//定义结果变量
long result;
//计算结果
if(n==1){
return 1;
}else{
result = n * fac(n-1);
}
//返回结果
return result;
}
}
例2:斐波那契数列
/**
* 功能:得到斐波那契数列,Fibonacci的第n项
斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,
377,610,987,1597,2584,4181,6765,10946,17711,28657,46368
特别指出:第1项是0,第2项是第一个1。
这个数列从第三项开始,每一项都等于前两项之和
技能:递归
解决方案1:循环
解决方案2:递归 fib(n)=fib(n-1)+fib(n-2) n>=3 fib(1)=0 fib(2)=1
*
* @豆皮没有豆
*/
public class YuFa41 {
public static void main(String[] args) {
//方式1:循环
int n = 20;
long num1 = 0;
long num2 = 1;
long numn = 0;
for(int i=3;i<=n;i++){
//得到第i项
numn = num1+num2;
//改变num1和num2的值
num1 = num2;
num2 = numn;
}
System.out.println("第"+n+"项是"+numn);
//方式2:递归
long result = fibo(n);
System.out.println("第"+n+"项是"+result);
}
public static long fibo(int n){
//1、定义结果变量
long result;
//2、计算结果
if(n==1){
return 0;
}else if(n==2){
return 1;
}else{
result = fibo(n-1)+fibo(n-2);
}
//3、返回结果
return result;
}
}
3. 递归的优点
代码简单
递归的缺点
递归调用会占用大量的系统堆栈,内存耗用多,
在递归调用层次多时速度要比循环慢的多
递归的使用场合
任何可用递归解决的问题也能使用迭代解决。
当递归方法可以更加自然地反映问题,并且易于理解和调试,并且不强调效率问题时,可以采用递归;
在要求高性能的情况下尽量避免使用递归,递归既花时间又耗内存。
第三章小结
图片来源:https://liaozhiwei.blog.csdn.net/article/details/82938411是个大咖哦