遞迴、迭代、動態規劃的區別與聯絡
阿新 • • 發佈:2018-12-21
一、定義
遞迴:程式呼叫自身,從頂部將問題分解,通過解決掉所有分解出來的小問題,來解決整個問題。 迭代:利用變數的原值推算出變數的一個新值。遞迴中一定有迭代,但是迭代中不一定有遞迴。 動態規劃:通常與遞迴相反,其從底部開始解決問題。將所有小問題解決掉,進而解決的整個問題。
下面通過斐波那契數列相關程式碼來比較一下三者。 斐波那契數列:1,1,2,3,5,8,11,13…
二、遞迴
自上而下呼叫函式本身,速度較慢,不推薦。
要知道第n個數,必須要先知道第n-1和第n-2個數。 而想要知道第n-1個數必須要先知道第n-2和第n-3個數, 想要知道第n-2個數必須要先知道第n-3和第n-4個數。
f(n) =f(n-1)+f(n-2) =f(n-2)+f(n-3)+f(n-3)+f(n-4) =…
int fibonacci(int n)
{
if (n <= 2)
return 1;
else
return fibonacci(n - 1) + fibonacci(n - 2);
}
三、迭代
利用原值去求解下一個值,一般比遞迴更加快速。
由第一個數和第二個數去求解第三個數, 由第二個數和第三個數去求解第四個數, 以此類推。
f(3)=f(2)+f(1) f(4)=f(3)+f(2) f(5)=f(4)+f(3) …
int fibonacci(int n) { if (n <= 2) return 1; int first = 1, second = 1, answer; for (int i = 3; i <= n; i++) { answer = first + second; first = second; second = answer; } return answer; }
四、動態規劃
動態規劃甚至比迭代還要更快一點,但是採用了空間換時間。
1、級問題的最優解包含了其子問題的最優解,也就是最優子結構性質。 2、有些子問題的可能需要多次計算,即子問題的重疊的性質。 3、子問題的解儲存在一張表格裡,這樣每個子問題只用計算一次。 4、需要額外的空間以節省時間。
int fibonacci(int n) { vector <int> dp; dp.push_back(0); dp.push_back(1); for (int i = 3; i <= n; i++) dp.push_back(dp[i-1] + dp[i-2]); return dp[n]; }