最長遞增子串行 LIS

2021-05-04 16:30:32 字數 1920 閱讀 1091

對於這個問題,最直觀的dp方法是cnt[i]表示以height[i]結束的最長遞增子串行的元素的個數,遞迴方程是cnt[i]=max

for(max=i=0;i求出整個數列的最長遞增子串行的長度

if(b[i]>max)

max=b[i];

cout< }

return 0; }

顯然,這種方法的時間複雜度仍為o(n^2);

3、對第二種思路的改進:

第二種思路在狀態轉移時的複雜度為o(n),即在找a[k]前面滿足a[j]#include

using namespace std;

int find(int *a,int len,int n)//若返回值為x,則a[x]>=n>a[x-1]

return left;}

void fill(int *a,int n)

int main()

for(max=i=0;i

if(b[i]>max)

max=b[i];

cout< }

return 0; }

對於這段程式,我們可以用演算法導論上的loop invariants來幫助理解.

loop invariant: 1、每次迴圈結束後c都是單調遞增的。(這一性質決定了可以用二分查詢)

2、每次迴圈後,c[i]總是儲存長度為i的遞增子串行的最末的元素,若長度為i的遞增子序

列有多個,剛儲存末尾元素最小的那個.(這一性質決定是第3條性質成立的前提)

3、每次迴圈完後,b[i]總是儲存以a[i]結尾的最長遞增子串行。

initialization:    1、進入迴圈之前,c[0]=-1,c[1]=a[0],c的其他元素均為1000,c是單調遞增的;

2、進入迴圈之前,c[1]=a[0],儲存了長度為1時的遞增序列的最末的元素,且此時長度為1

的遞增了序列只有乙個,c[1]也是最小的;

3、進入迴圈之前,b[0]=1,此時以a[0]結尾的最長遞增子串行的長度為1.

maintenance:   1、若在第n次迴圈之前c是單調遞增的,則第n次迴圈時,c的值只在第6行發生變化,而由

c進入迴圈前單調遞增及find函式的性質可知(見find的注釋),

此時c[j+1]>c[j]>=a[i]>c[j-1],所以把c[j]的值更新為a[i]後,c[j+1]>c[j]>c[j-1]的性質仍然成

立,即c仍然是單調遞增的;

2、迴圈中,c的值只在第6行發生變化,由c[j]>=a[i]可知,c[j]更新為a[i]後,c[j]的值只會變

小不會變大,因為進入迴圈前c[j]的值是最小的,則迴圈中把c[j]更新為更小的a[i],當

然此時c[j]的值仍是最小的;

3、迴圈中,b[i]的值在第7行發生了變化,因為有loop invariant的性質2,find函式返回值

為j有:c[j-1]長度,即為j-1,把a[i]接在c[j-1]後可得到以a[i]結尾的最長遞增子串行,長度為(j-1)+1=j;

termination:       迴圈完後,i=n-1,b[0],b[1],...,b[n-1]的值均已求出,即以a[0],a[1],...,a[n-1]結尾的最長遞

增子序列的長度均已求出,再通過第8行的迴圈,即求出了整個陣列的最長遞增子串行。

仔細分析上面的**可以發現,每次迴圈結束後,假設已經求出c[1],c[2],c[3],...,c[len]的值,則此時最長遞增子串行的長度為len,因此可以把上面的**更加簡化,即可以不需要陣列b來輔助儲存,第8行的迴圈也可以省略。

#include

using namespace std;

int find(int *a,int len,int n)//修改後的二分查詢,若返回值為x,則a[x]>=n

return left; }

int main()

cout< }

return 0; }

最長遞增子串行 LIS

給定乙個長度為n的陣列,找出乙個最長的單調自增子序列 不一定連續,但是順序不能亂 例如 給定乙個長度為6的陣列a,則其最長的單調遞增子串行為,長度為4.這個問題可以轉換為最長公共子串行問題。如例子中的陣列a,則我們排序該陣列得到陣列a 然後找出陣列a和a 的最長公共子串行即可。顯然這裡最長公共子串行...

最長遞增子串行(LIS)

300.longest increasing subsequence good 給定乙個長度為n的陣列,找出乙個最長的單調遞增子串行 不一定連續,當時先後順序不能亂 更正式的定義是 設l 是n個不同的實數的序列,l的遞增子串行是這樣乙個子串行lin 其中k1。比如陣列a 為,那麼最長遞增子串行為。以...

LIS 最長遞增子串行

最長遞增子串行可以用動態規劃的方法,時間複雜度是o n n 也可以用二分查詢的方法,時間複雜度是o nlogn 首先看二分查詢的方法 思路是,順序插入資料,當插入的資料大於以往的任何值時,插入到最後,若插入的資料不是大於以往的任何值時,首先找到大於要插入資料的乙個值,然後,將要插入的資料將該值替換掉...