递归
1.什么是递归:
程序调用自身的编程技巧称为递归( recursion)。递归作为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。
总结:递归就是方法在方法体里调用自身方法,但是需要有边界条件,递归前进段,和递归返回段。
2.案例讲解:
求一个数的阶乘: 比如数字5,它的阶乘为5*4*3*2*1=120;
普通方法:
普通方法:
int result =1;
private static int f1(int i) {
int result =1;
for (int j = i; j >0 ; j--) {
result *=j;
}
return result;
}
递归求解:
private static int f2(int i) {
if (i==1)return 1;
return i*f2(i-1);
}
下面是一个递归推进的图片,已经画得比较详细了。
总结:普通方法需要使用for循环实现,而递归函数只需要设置一下递归的边界,再设置递归规则。如果能理解的话,递归函数会更简单一些。下面再举一个列子说明:
斐波那契数列
斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、…… 求指定指定位置上的值是多少?
private static int f4(int i) {
if (i == 1) {
return 0;
} else if (i == 2) {
return 1;
}
int last1 = 1;
int last2 = 0;
int result = 0;
for (int j = 3; j <= i; j++) {
result = last2 + last1; //结果等于前两数之和
last1 = result; //将当前结果交给前一个值保存
last2 = last1; //将上一个值交给上第二个值保存
}
return result;
}
递归求解:
private static int f3(int i){
if (i==2)return 1;
if (i==1)return 0;
return f3(i-1)+f3(i-2);
}
对比上两个方法:
递归的写法简直太简单了,下面详细讲解一下递归的过程:
1.首先运用递归需要查找规律,并找到它的边界条件,并用逆向思维从最后一步推演:
0、1、1 、2 、3 、5 、8 、13 、21、34.....
0、1、1+0、1+1、1+2、2+3 、3+5、5+7、........即 n[i]=n[i-1]+n[i-2]
可以看出这组数列的规律为,后一位数等于前两位数字之和. 且它的边界是第一个和第二个数字恒定不变.
2.如果要求其中一个指定位置的数值,可以定义求它的方法为: public int f(i)
那么用函数表示规律即是: f(i)=f(i-1)+f(i-2);
3.所以在写递归的时候:
先定义方法,
再设定方法的边界(如果没有边界就会无限循环)
再设定返回值,反复调用函数.
递归的优缺点:
递归的优点:代码简单,理解了逻辑也很简单.
递归的缺点:
递归解题相对常用的算法如普通循环等,运行效率较低。因为每一次调用函数,都要在栈内存中开辟空间存储里面的变量,如果遍历的次数过多,还会栈内存溢出.