原文链接:http://blog.csdn.net/qq_22329521/article/details/52967839
递归的显著缺点
递归由于调用自身,而函数调用是有时间和空间的消耗的:每一次函数调用,都需要在内存栈中分配内存空间以保存参数、返回地址及临时变量,而且往栈里压入数据和弹出数据都需要时间。
另外,递归中有可能很多计算都是重复的,从而对性能带来很大的负面影响。递归的本质是把一个问题分解成两个或者多个小问题。如果多个小问题存在互相重叠的部分,那么久存在重复的计算。
斐波那契数列
效率最低的解法
//递归调用
long fibonacci(int n){
if(n<=0){
return 0;
}
if (n==1){
return 1;
}
return fibonacci(n-1)+fibonacci(n-2);
}
树中有多个结点是重复的,而且重复的结点数会随着n的增加而急剧增加,这意味着随着n增加。用递归方法计算的时间复杂度是以n的指数的方式递增的
改进的方式,只要避免重复计算,将得到的数列中间值保存起来,下次要计算查找一下
更简单的方式是从下往上走,计算f(0)和f(1)的f(2)以此计算
public static int fibonaci(int n) {
int result[ 2]={
0, 1
} ;
if (n < 2) return result[n];
long fibNMinusOne=1;
long fibNMinuesTwo=2;
long fibN=0;
for(int i =2;i<=n;i++){
fibN = fibNMinusOne+fibNMinuesTwo;
fibNMinuesTwo = fibNMinusOne;
fibNMinusOne =fibN;
}
return fibN;
}
青蛙跳题目(扩展)
一只青蛙一次可以跳上一个台阶,也可以跳上2个台阶,求青蛙跳上一个n级台阶共有多少总跳法
思路:如果只有1级台阶,显然只有一种跳法,如果两个台阶,就来有种跳法
一般情况下,我们把n级台阶时的跳法看成是n的函数,记为f(n)。当n>2时,第一次跳的时候就有两种不同的选择:一是第一次只跳1级,此时跳法数目等于后面剩下的n-1级台阶的跳法数目,即为f(n-1);另一种选择是第一次跳2级,此时跳法数目等于后面剩下的n-2级台阶的跳法数目即为f(n-2)因此n级台阶的不同跳法总数是f(n)=f(n-1)+f(n-2)
青蛙跳扩展2
如果一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。。。它也可以跳上n级台阶,此时青蛙跳上一个n级台阶共有集中跳法,用数学的归纳法可以证明是f(n)=2^{(n-1)}
格子覆盖问题(扩展)
我们可以用2x1 的小矩形横着或者竖着去覆盖更大的矩形如8个2x1 的小矩形无重叠的覆盖一个2x8的大矩形,共有几种方法
思路:我们先把2x8的覆盖方法记为f(8)用第一个1x2小矩形去覆盖大矩形的最左边两个选择,竖着或者横着放,当竖着放,右边还剩下2x7的区域,它的覆盖方法即为f(7)。然后考虑横着放的情况。当1x2的小矩形横着放在左上角的时候,左下角必须和横着放一个1x2的小矩形,而在右边还剩下2x6的区域,这种情形下的覆盖方法记为f(6),因此f(8)=f(7)+f(6)也是个斐波那契数列