青蛙跳台階問題及尾遞迴優化方法

2021-08-30 17:53:57 字數 3365 閱讀 8819

目錄

問題一了解遞迴和迭代

了解尾遞迴

如何將普通遞迴優化為尾遞迴?

有關遞迴和尾遞迴優化的文章可以參考

其它尾遞迴優化參考

問題二尾遞迴的練習:

現有n階台階,有乙隻青蛙要從台階底跳上台階頂。這只青蛙每次可以跳一階,也可以跳兩階。問這只青蛙有多少種跳法可以完成目標?

分析:這種問題可以先從簡單情況著手,記總共有jump(n)種方法。

當n=1時,jump(1) = 1; // 1

當n=2時,jump(2) = 2; // 1+1、2

當n=3時,jump(3) = 3; //1+1+1、 1+2先跳一步,再跳兩步(jump(2))、2+1先跳兩步,在跳一步

當n=4時,jump(4) = 5; //參考n=3思考過程

此時,我們發現規律為:

jump(1) = 1;   jump(2) = 2;

jump(n) = jump(n-1) +jump(n-2) n >2; 

//形式上為斐波那契數列

function jump(n)

if (n ==1 || n ==2) else

}console.time('jump');

console.log(jump(5)); //8 jump: 2.552978515625ms

console.log(jump(40)); //165580141 jump: 927.423095703125ms

console.endtime('jump');

仔細看一眼返回值,發現函式使用了遞迴,當呼叫過深時,耗時非常長,而且可能會造成爆棧;下面談談遞迴和迭代。

迭代:我們經常在for迴圈中寫這樣的語句: res += num; 表示將當前res值與num求和,再賦值給res,這種就i是迭代。

遞迴:參考我們上面的**,遞迴可以理解為一種思想,將乙個複雜的問題分解為簡單一點的問題,此問題與原問題解法相似,直到回退為乙個基本的情景作為遞迴的出口

遞迴的優點:1)**簡潔  2)思想清晰,易於理解

遞迴的缺點:函式呼叫是通過乙個工作棧來實現的,遞迴操作需要反覆呼叫函式自身,在這個過程中需要儲存函式執行產生的區域性變數,直到遇到基本情況時(遞迴出口),儲存的區域性變數才會被釋放。也就是說,隨著遞迴層級的逐漸深入,系統需要更多的空間去儲存上一級產生的區域性變數,這產生了巨大的效能問題。

尾遞迴顧名思義就是函式的返回值返回遞迴函式本身。

遞迴由於效率低的問題,經常要求轉換成迴圈結構的非遞迴形式。那這個迴圈結構跟我們要使用尾遞迴有什麼關聯?

不是尾遞迴本身可以優化**效能,而是尾遞迴可以通過一些編譯器轉化為迴圈結構,而迴圈結構的**相對遞迴形式效率有所提高。

//斐波那契數列的尾遞迴優化

//簡單分析,將遞迴轉化為迴圈/迭代結構,那就需要乙個與迴圈結構相似的特徵:迴圈次數,這裡我們記為i

//規定了迴圈次數之後,可以有兩種策略進行計數

//公升序 i =1 -> n

function upperjump(n, i=1, pre=1, cur=1)

if (n==1 || n==2)

if (i == n)else

} console.time('upperjump');

console.log(upperjump(5));//8 tailjump: 0.27978515625ms

console.timeend('upperjump');

//降序 i=n -> 1

function downjump(n, i, pre=1, cur=1)else

} console.time('downjump');

console.log(downjump(5,5));//8 downjump: 2.082275390625ms

console.timeend('downjump');

漫談遞迴轉非遞迴

劍指offer面試題9-青蛙跳台階及其變種問題 

青蛙產生了變異,不但可以一次跳一階,也可以一次跳兩階。。。也可以一次跳n階。同問對於n階台階,這個青蛙有多少中跳法?

分析

當n=1時,jump(1) = 1; // 1

當n=2時,jump(2) = 2; // 1+1、2

當n=3時,jump(3) = 4; //1+1+1、 1+2先跳一步,再跳兩步(jump(2))、2+1先跳兩步,在跳一步 、3一次跳三步

當n=4時,jump(4) = 8; //1+(ju***)、 2+ (jump(2))、3+(jump(1))

。。。當n = n時,jump (n)= jump(n-1) +jump(n-2) +...+jump(1);

對於上面的表示式,可簡化為 jump(n) = 2* jump(n-1),邊界條件 n=1時,jump(1) = 1;

function btjump(n)else

return res;

} console.time('btjump');

console.log(btjump(5));//16 btjump: 3.189208984375ms

console.timeend('btjump');

此時我們發現了,這依然時遞迴(注意與尾遞迴區別)。

//同上,我們用i計數,直到i=n時,返回結果res

//下面**為計數公升序

function upperbtjump(n, i=1, res=1)

if (i ==n) else

} console.time('upperbtjump');

console.log(upperbtjump(5));//16 upperbtjump: 0.152099609375ms

console.timeend('upperbtjump');

階乘n!

遞迴求解青蛙跳台階問題

1.乙隻青蛙一次可以跳上1級台階,也可以跳上2級台階,問這個青蛙跳上n級台階一共有多少種跳法 思路一 和漢諾塔一樣,遞迴的思路就是把問題簡化到更小規模的問題,在寫程式的時候確定兩個目標。一是如何分解乙個問題,二是當該問題分解到最簡時如何處理,將這兩塊內容通過程式告訴電腦,就可以把任務推給電腦,由電腦...

青蛙跳台階問題

題目 乙隻青蛙一次可以跳上 1 級台階,也可以跳上2 級。求該青蛙跳上乙個n 級的台階總共有多少種跳法。我的思路 最開始我的思路是把這個看成是乙個數學問題,n i 1 k 2先把所有可能滿足這個公式的i和k求出來。然後在對i和k做排列組合。很明顯i的範圍應該是0 public int jumpflo...

青蛙跳台階問題

1 乙隻青蛙一次可以跳上 1 級台階,也可以跳上2 級。求該青蛙跳上乙個n 級的台階總共有多少種跳法。2 乙隻青蛙一次可以跳上1級台階,也可以跳上2 級 它也可以跳上n 級,此時該青蛙跳上乙個n級的台階總共有多少種跳法?分析 1 當n 1,只有1中跳法 當n 2時,有兩種跳法 當n 3 時,有3種跳...