經典動態規劃問題 最長上公升子串行 LIS

2021-09-05 09:58:11 字數 1888 閱讀 2750

目錄

最長上公升子串行:

o(n^2)動態規劃:

o(n*logn):貪心+二分

乙個數的序列bi,當b1 < b2 < … < bs的時候,我們稱這個序列是上公升的。對於給定的乙個序列(a1, a2, …, an),我們可以得到一些上公升的子串行(ai1, ai2, …, aik),這裡1 <= i1 < i2 < … < ik <= n。

狀態:dp[i],表示以a[i]為結尾陣列的的最長上公升子串行長度

初始化:a[i]的最長上公升子串行最小為1,也就是左邊的數都大於等於a[i],最長上公升子串行只有a[i]元素本身,dp[i] = 1;

dp[i]表示以a[i]的最長子序列長度,我們現在找倒數第二個元素。

遍歷a[0,...i-1],設其中小於a[i]的元素為a[k,j,z...],倒數第二個元素必定在a[k,j,z]中,dp[i]有幾種可能:

dp[i] = dp[k]+1;

dp[i ]= dp[j]+1;

dp[i] = dp[z]+1;

取這幾種可能結果中的最大值,即為dp[i]的值。

最後返回的則是dp陣列中的元素最大值。

class longestincreasingsubsequence ;

for(int i = 0;i這道題還有複雜度更低的做法, 可在面試中作為演算法的優化,同時能夠返回最長上公升子串行的元素值。

從左到右遍歷陣列,用dp陣列維護當前的最長上公升子串行,size變數維護最長上公升子串行的長度。

如a=a[0]等於2,dp = ,size=1;

a [1]等於1,小於dp的末尾元素2,因此讓1把2替換掉,dp = ,size = 1;長度為1的最長子序列,結尾元素為1顯然比結尾元素為2的序列更容易加"上公升元素"

a [2]等於3,大於dp的末尾元素1,因此dp中加入2,dp = ,size = 2;

a [3]等於4,大於dp的末尾元素2,因此dp中加入4,dp = ,size = 3;

a [4]等於8,大於dp的末尾元素4,因此dp中加入8,dp = ,size = 4;

a [5]等於6,小於dp的末尾元素8,大於倒數第二個元素4,因此將6替換8,dp = ,size = 4,因為長度為4的最長上公升子串行,結尾是6會比結尾是8的序列要更有利於新增新元素。

得到最長上公升子串行為,長度為4;

這裡使用了貪心策略:乙個上公升子串行,最後乙個元素越小,越有利於新增後續比它大的元素。

dp為有序陣列,因此若a[i]小於dp末尾元素,需要找到dp中第乙個大於等於a[i]的元素並讓a[i]替換掉它。(較小的值越往前面約好)

注意這裡的二分查詢是求下界的,即》=所查詢物件的第乙個位置。

class longestincreasingsubsequence ;

int size = 0;

dp[size++] = a[0];

for(int i = 1;idp[size-1])//當前元素大於dp陣列中的最後乙個元素

dp[size++] = a[i];

else

}return size;

}};

此外在求陣列中第乙個大於等於a[i]的值時,可以使用lower_bound()

lower_bound(int* first,int* last,val);函式在(first,last](左開右閉)區間中進行二分查詢。因此陣列必須是排好序的陣列。

函式返回從first開始的第乙個大於或等於val的元素的位址。如果所有元素都小於val,則返回last的位址。

第乙個大於等於a[i]的陣列下標為:pos =   lower_bound(dp,dp+size,a[i])-dp

因此  int firstbig = dp[pos];

動態規劃 最長上公升子串行問題

原文 主題 動態規劃 最長上公升子串行問題,也就是longest increasing subsequence,縮寫為lis。是指在乙個序列中求長度最長的乙個上公升子串行的問題,是動態規劃中乙個相當經典問題。在這裡我們可以看到,這個上公升實質上就是乙個對 進行定義的過程,所以我們求解的其實是一類問題...

最長上公升子串行問題(動態規劃)

乙個數的序列bi,當b1 n。比如,對於序列 1,7,3,5,9,4,8 有它的一些上公升子串行,如 1,7 3,4,8 等等。這些子串行中最長的長度是4,比如子串行 1,3,5,8 你的任務,就是對於給定的序列,求出最長上公升子串行的長度。輸入輸入的第一行是序列的長度n 1 n 1000 第二行給...

動態規劃 最長上公升子串行

問題描述 乙個數的序列bi,當b1 b2 bs的時候,我們稱這個序列是上公升的。對於給定的乙個序列 a1,a2,an 我們可以得到一些上公升的子串行 ai1,ai2,aik 這裡1 i1 i2 ik n。比如,對於序列 1,7,3,5,9,4,8 有它的一些上公升子串行,如 1,7 3,4,8 等等...