題目描述
乙隻青蛙一次可以跳上1級台階,也可以跳上2級。求該青蛙跳上乙個n級的台階總共有多少種跳法(先後次序不同算不同的結果)。
示例1:
輸入1
返回值1
示例2:
輸入4
返回值5
思想: 經典遞迴問題
思路:跳n級台階相當於n-
1和n-
2級台階的和
原因:n級台階就相當於n-
1級再跳一次一階的和n-
2級再跳一次2階的
public
class
solution
}
優化後的**:
public
class
solution
else
}}
優化的原因:
遞迴存在的問題
遞迴呼叫層級太多,導致棧溢位問題
遞迴重複計算,導致效率低下
棧溢位問題
每一次函式呼叫在記憶體棧中分配空間,而每個程序的棧容量是有限的。
當遞迴呼叫的層級太多時,就會超出棧的容量,從而導致呼叫棧溢位。
其實,我們在前面小節也討論了,遞迴過程類似於出棧入棧,如果遞迴次數過多,棧的深度就需要越深,最後棧容量真的不夠咯
要計算原問題 f(10),就需要先計算出子問題 f(9) 和 f(8)
然後要計算 f(9),又要先算出子問題 f(8) 和 f(7),以此類推。
一直到 f(2) 和 f(1),遞迴樹才終止。
我們先來看看這個遞迴的時間複雜度吧,「遞迴時間複雜度 = 解決乙個子問題時間*子問題個數」
乙個子問題時間 = f(n-1)+f(n-2),也就是乙個加法的操作,所以複雜度是 「o(1)」;
問題個數 = 遞迴樹節點的總數,遞迴樹的總結點 = 2n-1,所以是複雜度「o(2n)」。
因此,青蛙跳階,遞迴解法的時間複雜度 = o(1) * o(2^n) = o(2^n),就是指數級別的,**增長的,「如果n比較大的話,超時很正常的了」。
回過頭來,你仔細觀察這顆遞迴樹,你會發現存在「大量重複計算」,比如f(8)被計算了兩次,f(7)被重複計算了3次…所以這個遞迴演算法低效的原因,就是存在大量的重複計算!
「那麼,怎麼解決這個問題呢?」
既然存在大量重複計算,那麼我們可以先把計算好的答案存下來,即造乙個備忘錄,等到下次需要的話,先去「備忘錄」查一下,如果有,就直接取就好了,備忘錄沒有才再計算,那就可以省去重新重複計算的耗時啦!這就是「帶備忘錄的解法」
我們來看一下「帶備忘錄的遞迴解法」吧~
一般使用乙個陣列或者乙個雜湊map充當這個「備忘錄」。
假設f(10)求解加上「備忘錄」,我們再來畫一下遞迴樹:
「第一步」,f(10)= f(9) + f(8),f(9) 和f(8)都需要計算出來,然後再加到備忘錄中,如下:
「第二步,」 f(9) = f(8)+ f(7),f(8)= f(7)+ f(6), 因為 f(8) 已經在備忘錄中啦,所以可以省掉,f(7),f(6)都需要計算出來,加到備忘錄中~
「第三步,」 f(8) = f(7)+ f(6),發現f(8),f(7),f(6)全部都在備忘錄上了,所以都可以剪掉。
遞迴求解青蛙跳台階問題
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種跳...