目录
一、生活中的实例
四个小伙伴参加考试,遇到一个谁都不能独立解决的难题,但每个人还能回答上一部分来。所以他们决定共同合作,用前后传纸条的方式交流。四个人坐成一列,分别是同学A,B,C,D,而他们遇到的难题是:四大名著有哪些?
A只知道有《三国演义》,只能求助了,纸条传给B: 四大名著除了《三国演义》还有什么?
-->B想了想纸条传给C: 四大名著除了《三国演义》《水浒传》还有什么?
-->C想了想纸条传给D:四大名著除了《三国演义》《水浒传》《红楼梦》还有什么?
-->D想了想写完了考题,回复给C:我知道答案了,四大名著是《三国演义》《水浒传》《红楼梦》《西游记》
--> C回复B:我知道答案了,四大名著是《三国演义》《水浒传》《红楼梦》《西游记》
-->B回复A:我知道答案了,四大名著是《三国演义》《水浒传》《红楼梦》《西游记》
--最后A收到信息,得到了答案。
这个例子有一个明显的特征:自身中包含了自己,有时候,我们遇到的问题直接并不好解决,但是发现将原问题拆分成其子问题之后,子问题与原问题有相同的解法,等子问题解决之后,原问题就迎刃而解了。
二、概念
递归:一个方法在执行过程中调用自身,就称为"递归".
使用场景:把一个较为复杂的原问题层层转化为与原问题相似的规模较小的问题。
优点:代码简洁。
缺点:难以理解。
示例:求N的阶乘。
import java.util.Scanner;
public class Lhj {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int x=sc.nextInt();
int ret1=factor1(x);
System.out.println("该数的阶乘为:"+ret1);
int ret2=factor2(x);
System.out.println("递归算法该数的阶乘为: "+ret2);
}
public static int factor1(int n) {
int sum=1;
for(int i=n;i>1;i--){
sum=sum*i;
}
return sum;
}
public static int factor2(int n){ //递归算法
if(n==0||n==1){ //递归的结束条件
return 1;
}else{
return n*factor2(n-1); //factor2函数调用自身
}
}
}
三、实现条件
从上面求N的阶乘的例子中,可以看出要实现递归,必须满足:
1、要对原问题进行拆分,拆分成一个个小的问题,且小问题与大问题解法相同。
2、要有递归的出口。
四、常见表现方式
1、问题本身递归
2、数据结构递归
3、概念递归
五、执行过程分析
以4的阶乘为例:
执行过程图:顺序为1-6。
从栈帧的角度来看:顺序为1-10。其中1-5是为每个方法创建栈帧,6-10为得到返回值后栈帧的销毁。从中也可以看出递归算法的本质。
六、练习
1.按顺序打印一个数字的每一位:
import java.util.Scanner;
public class Lhj {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int num=sc.nextInt();
printNum(num);
}
public static void printNum(int n){
if(n>9){
printNum(n/10);
}
System.out.print(n%10+" ");
}
}
/*
执行结果:
键入1234,输出1 2 3 4;
*/
2.求斐波那契数列第N位,这里值得思考的是,求斐波那契数列第N位用递归算法是效率很低的,因为当位数比较大时,会进行多次重复运算,如果用循环方法,就可以解决运算冗余的问题。
import java.util.Scanner;
public class Lhj {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int num=sc.nextInt();
int ret=fib(num);
System.out.println("第"+num+"位为"+ret);
}
public static int fib(int n) { //斐波那契数列:1 1 2 3 5 8 13 ...
if (n == 1 || n == 2) {
return 1;
}
return fib(n-1)+fib(n-2);
}
}
/*
执行结果:
键入6,结果为8。
*/
3.计算1-n的和
import java.util.Scanner;
public class Lhj {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int ret=add(n);
System.out.println("1到"+n+"的和为"+ret);
}
public static int add(int num) {
if(num==1){
return 1;
}else{
return add(num-1)+num;
}
}
}
/*
执行结果:
键入50,结果为1275。
*/
Over!!!