1. 程式人生 > >遞迴、迭代、動態規劃的區別與聯絡

遞迴、迭代、動態規劃的區別與聯絡

一、定義

遞迴:程式呼叫自身,從頂部將問題分解,通過解決掉所有分解出來的小問題,來解決整個問題。 迭代:利用變數的原值推算出變數的一個新值。遞迴中一定有迭代,但是迭代中不一定有遞迴。 動態規劃:通常與遞迴相反,其從底部開始解決問題。將所有小問題解決掉,進而解決的整個問題。

下面通過斐波那契數列相關程式碼來比較一下三者。 斐波那契數列: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];
}