小明學演算法 1 動態規劃 最長遞增子串行問題

2022-05-16 14:50:43 字數 2343 閱讀 1031

一.概念介紹

動態規劃(dynamic programming),簡稱dp.是把多階段過程轉化為一系列單階段問題,利用各階段之間的關係,逐個求解,創立了解決這類過程優化問題的新方法.

二.特點

動態規劃演算法通常基於乙個遞推公式及乙個或多個初始狀態。當前子問題的解將由上一次子問題的解推出。使用動態規劃來解題只需要多項式時間複雜度,因此它比回溯法、暴力法等要快許多。

在解決問題時,推導出狀態轉移方程是關鍵所在.

三.舉例

1.最少硬幣問題

待續...

2.lcs問題

最長公共子串行的長度問題的推導公式為:

從公式可知,這個問題可以用遞迴的方式來實現,**:

1

//遞迴實現方法 lcs(i,j)即公式中的c[i,j]

2int lcs(int i, intj)3

18 }

view code

遞迴實現雖然好理解,但是存在缺陷,不能記錄所有的資料改變的記錄,而資料改變的記錄可以在長度外,幫助找到子串行.

用陣列pd代替公式中的二維陣列c[i][j],完成上述公式的**如下:

1 #include2 #include3 #include

4using

namespace

std;

5char a[10], b[10];6

intlena, lenb;78

void

lcs();

9int

main()

1022

void

lcs()

2340

else

4145}46

}4748 cout <

49 cout <

50 }

view code

用陣列實現的時候,有乙個好處,我們發現了乙個規律,相同字元所對應的c[i][j]的賦值一定是它左上側c[i-1][j-1]的值加一得來的,如下圖所示,所以我們通過倒序遍歷陣列c的賦值過程,可以得到最長自序列.

倒序遍歷時,我們需要記載當前c[i][j]被賦值時的方向,引入了乙個陣列來記載c[i][j]的賦值方向.然後倒序遍歷則可以得到結果,**如下:

1 #include2 #include3 #include

4using

namespace

std;

5char a[10], b[10];6

intlena, lenb;78

int lcs(int, int); ///

兩個引數分別表示陣列a的下標和陣列b的下標

9void

lcs();

10int

main()

1123

24void

lcs()

25 };

30//

用來記錄賦值的方向

31char dpd[11][11

];32

3334

//公式第一段

35 dp[0][0] = 0;36

for (int i = 0; i < m; i++)

3747

else

4858

else

5964

65 dp[i + 1][j + 1] =t;66}

67}68}

6970 cout <

71 cout <

7273

while (m>=0&&n >= 0)74

8283

switch

(dpd[m][n])

8496}97

98 }

view code

結果:

3.遞增子串行問題

遞推公示:length[i]=a[i]>a[0...i-1]?length[i-1]+1:max

動態規劃 最長遞增子串

給定乙個陣列nums,求其最長的遞增子串長度。如陣列 10,9,2,5,3,7,101,18 其最長遞增子串為 2,3,7,101 長度為4.方法一 直接遍歷,複雜度為o n 2 方法二 把長度為i 1的遞增子串的最後元素的最小值記錄在陣列tails中,如對於陣列 4,5,6,3 tails中的記錄...

動態規劃 最長遞增子串行

給出序列 1 2 3 4 2 5 3 4 a 1 1,a 2 2,a 7 3,a 8 4 求其最長的遞增子串行,以上最長遞增子串行為 1 2 3 4 5 問題細分 初始化條件f 1 1,序列只有1個長度即為1 f 2 a 2 與下標小於2的比較,即a 1 比較,a 2 a 1 因此更新f 2 f 1...

動態規劃 最長遞增子串行

給定乙個無序的整數陣列,找到其中最長上公升子串行的長度 例項 輸入 10,9,2,5,3,7,101,18 輸出 4 解釋 最長的上公升子串行為 2,3,7,101 長度為4說明 可能會有多種最長上公升子串行的和,只需要輸出對應長度即可 演算法的時間複雜度應為o n2 首先,dp陣列的定義如下 dp...