動態規劃 LIS

2021-08-09 23:24:34 字數 2533 閱讀 5556

動態規劃是比較重要的演算法啦,打算慢慢寫幾篇部落格總結一下。

動態規劃的基本思想是:要求原問題的解,先求出更小一些的問題的解,由子問題的解通過某種方式得到原問題的解。

以上是有關動態規劃的一些基本概念和概括。

第一篇就先講一下最長遞增子串行(lis)的問題的解決。

給出乙個數列a,求a的乙個 長度最大的子數列b,使得b是乙個遞增數列

example:

數列a: 5, 2, 8, 6, 3, 6, 9, 7

乙個遞增的子數列: 5, 8, 9

乙個長度最大的遞增子數列:2, 3, 6, 9

將每乙個數作為乙個結點。從結點u到結點v連一條邊,當且僅當u代表的數在原數列中出現在v代表的數前面,而且u代表的數比v代表的數小。這樣轉化保證了dag(有向無環圖)的路徑和原數列的遞增子串行一一對應,因而dag上的最長路就是原數列的最長遞增子串行。

#include

#include

#include

using

namespace std;

intmain()

vector<

int> result;

result.

assign

(nums.

size()

,1);

for(

int i =

1; i < nums.

size()

; i++)}

result[i]=1

+ max;

}int max =0;

for(

int i =

0; i < result.

size()

; i++

) cout << max << endl;

}

有n個狀態,每個狀態遷移的複雜度是o(n),因而總複雜度為o(n^2)。

我們可以看到,在生成遞增子串行中,有一些值是不需要維護,可以直接去掉的,這樣做可以減少狀態遷移的複雜度。

考慮這樣乙個事情,遍歷陣列的時候,比如,例子中所給的:

5, 2, 8, 6, 3, 6, 9, 7

第乙個數5,直到當前,最長遞增序列有1個數。

第二個數2,直到當前,最長遞增序列還是只有1個數。

此時,無論後面的數是什麼,只需要這個數比2大,那麼就能將最長遞增序列增加到兩個數。而5已經沒有價值了。因為乙個數若大於5必定大於2,而且與2相比,更有可能獲取更長的遞增序列。

簡單來說,就是維護乙個結果陣列,陣列表示結果需要的遞增數列的每乙個值,陣列的長度就是最長遞增序列的長度。(當然,結果不唯一)

vector<

int> result;

result.

push_back

(nums[0]

);for(

int i =

1; i < nums.

size()

; i++

)else

if(result[index]

> nums[i]

)}

通過二分查詢,找到遍歷到的數在結果陣列中的位置(即找到第乙個比該數大的數在結果陣列中的下標),如果該位置不存在,表示比結果陣列中所有的數都大,那麼插入該數到結果陣列的尾部。否則,判斷該數是否比該位置的數小,如果是,替換之。

#include

#include

using

namespace std;

//find the index that the num should be inserted

intbinary_search

(int low,

int high, vector<

int>

& nums,

int num)

return low;

}int

binary_search_recursion

(int low,

int high, vector<

int>

& nums,

int num)

else

}int

main()

vector<

int> result;

result.

push_back

(nums[0]

);for(

int i =

1; i < nums.

size()

; i++

)else

if(result[index]

> nums[i])}

cout << result.

size()

<< endl;

}

可以看到n次遍歷,每次遍歷二分查詢的複雜度為o(log n),總的複雜度是o(n*log n)

動態規劃 LIS

最長遞增子串行 lis 的問題是要找到乙個給定序列的最長子序列的長度,使得子串行中的所有元素被排序的順序增加。例如,lis的長度是6和 lis為。最優子結構 對於長度為n的陣列a n 假設假設我們想求以aj結尾的最大遞增子串行長度,設為l j 那麼l j max l i 1,where i j a ...

動態規劃 LIS

lis指乙個序列中最長的單調遞增 嚴格 的子串行。有一種較為樸素的o n 2 的做法,我們不多做贅述,我們講一種用單帶棧和二分來實現的o logn 的演算法 我們從1 n列舉,若該數比棧頂元素大,那麼我們就將該數壓入棧中。否則我們就在整個棧中二分到乙個第乙個大於等於它的數,將其用a i 替換。考慮為...

動態規劃 LIS問題

最長上公升子串行 longest increasing subsquence 即lis問題是動態規劃解決的乙個經典問題。例如輸入序列1 5 2 3 4 輸出最長上公升子串行的長度 4 子串行為1 2 3 4 動態規劃思路 dp i 為最長子序列最後乙個元素為元序列第i個元素是的最大長度,只要把前面比...