首先通過斐波那契數列引出兩個概念
斐波那契數列:
已知f(0)=0, f(1)=1, f(n)= f(n-1)+ f(n+2)分別用兩種不同的思想求得 f(n)。
解決遞迴問題,首先要明確函式定義,然後尋找遞迴終止條件,最後要能夠準確的寫出遞迴子式,即明確遞迴過程。
def
f(n)
:if n ==0:
return
0if n ==1:
return
1return f(n-1)
+ f(n-
2)
但在上述遞迴**中有好多是會重複計算的,為了改進,可以將已經計算的結果儲存下來,這就引出了記憶化搜尋;
將記憶化搜尋通過**的方式實現,結果如下:
mery =[-
1]*(n+1)
defnew_f
(n):
if n ==0:
return
0if n ==1:
return
1if mery[n]==-
1:mery[n]
= new_f(n-1)
+ new_f(n-2)
return mery[n]
斐波那契數列用動態規劃的思想解決的話,**如下:
def
dp(n)
: mery =[-
1]*(n+1)
for i in
range(0
, n+1)
:if i ==0:
mery[i]=0
elif i ==1:
mery[i]=1
else
: mery[i]
= mery[i-1]
+ mery[i-2]
return mery[n]
此時,仔細品兩種做法,以斐波那契數列問題為例,發現f(n)和前兩項有關,遞迴的做法是從f(n)開始,不斷去求前一項,直至滿足遞迴終止條件;再看動態規劃,同樣發現發現f(n)和前兩項有關,動規的做法是從第一項開始求,直至求得第n項。
兩者的主要區別:兩者最大的區別是思考問題的方式不同,遞迴是一種自上而下的思考方式,遞迴是一種自下而上的思考方式。當遞迴層數過深的話,容易產生堆疊溢位的問題。
以青蛙**跳台階問題為例:
乙隻青蛙一次可以跳上1級台階,也可以跳上2級……它也可以跳上n級。求該青蛙跳上乙個n級的台階總共有多少種跳法。(題目**於牛客網)
首先看遞迴的做法:
# -*- coding:utf-8 -*-
class
solution
:def
jumpfloorii
(self, number)
:# write code here
mery =[-
1]*(number+1)
defdp
(n):
if n ==
1or n ==0:
return
1#遞迴終止條件
if mery[n]==-
1:tmp =
0for i in
range(1
,n+1):
tmp += dp(n-i)
mery[n]
= tmp
return mery[n]
return dp(number)
再看動規的做法:
# -*- coding:utf-8 -*-
class
solution
:def
jumpfloorii
(self, n)
:# write code here
dp =[0
]*(n+1
) dp[0]
=1for i in
range(1
,n+1):
tmp =
0for j in
range(0
,i):
tmp += dp[j]
dp[i]
= tmp
return dp[n]
關於遞迴和動態規劃的簡單理解
簡單的來說,遞迴就是乙個概念能夠用自身來解釋,比如說一本字典,每個字詞的解釋是依靠字典中其他的字詞來解釋的。一般來說,計算機中遇到的遞迴問題大多是把乙個問題分解成規模更小的子問題求解,再進行合併。乙個具有遞迴性質的問題,大多具有兩個特徵,第乙個是狀態轉移方程也就是遞迴方程,比如在求解階乘時,n!n ...
遞迴和動態規劃
暴力遞迴 1,把問題轉化為規模縮小了的同類問題的子問題 2,有明確的不需要繼續進行遞迴的條件 base case 3,有當得到了子問題的結果之後的決策過程 4,不記錄每乙個 子問題的解 動態規劃 1,從暴力遞迴中來 2,將每乙個子問題的解記錄下來,避免重複計算 3,把暴力遞迴的過程,抽象成了狀態表達...
動態規劃初步
基本原理 類似於遞迴解題,把問題丟給上一層來解決,找出狀態轉換方程即可。當然關鍵問題是如何定義遞迴陣列與找出狀態轉換方程。hello world 走樓梯 有n階樓梯,每次能走一步或兩步,請問有多少種走法。設f n 是n階樓梯不同的走法。則轉移到此狀態的方法有兩種,從n 1階樓梯走一步上來,或者從n ...