原文鏈接: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)也是個斐波那契數列