非降序列(increasing sequence)例如:
(1) 完全遞增型序列:s=
(2) 部分存在等於的序列:s=
s的非降子串行:由原序列s的元素組成的(且保持元素之間的順序不變的)組成的序列。
例如s=的子串行包括:
1個元素的:,,,,, 等6個子序列
2個元素的:,,,,,,,, 等
3個元素的:,
最長非降子串行(longest increasing sequences,lis),是s的所有非降子串行中包含元素最多的那些子串行,例如上述序列的最長子串行為和
而最長非降子串行的長度就是最長非降子串行的元素個數,例如上例中的最長非降子串行的長度為3。
求解序列s的最長非降子串行的長度通常採用動態規劃演算法:
設d(i)為前i個元素的最長非降子串行的長度,則d(i)=max, 其中 0<=j<=i,且s[j]然後寫出類似這樣的**:
publicstatic
void lis(int
s) }}
for(int i=0;i)
}
然後,呼叫該lis函式,求解。如
intseq=;lis(seq);
會輸出:1 1 2 3 3 4 ,代表包含前1個元素的lis長度為1,包含前2個元素的子串行的lis長度為1,包含前3個元素的子串行的lis長度為2,。。。
需要注意的是:上述遞推公式,d(i)=max, 其中 0<=j<=i,且s[j]只適用於
以s[i]作為結尾元素的lis序列。
而如果去掉以s[i]作為結尾元素這個條件,就不能這麼求解。
例如int [ ]seq=, 用上述程式求解,會輸出1 1 2 1 3 2 (即d[3]=1 ,d[5]=2,分別代表包含前4個元素子串行的lis長度為1,包含前6個元素子串行的lis長度為2)。但其實包含前4個元素的子串行(即)的lis的長度應該是2,即,d[3]=2, lis=或, 而 d[5] 應該是3。
問題出在,上述的程式要求lis以s[i]作為結尾,即lis的最大元素為s[i],這時d[i]=max是沒錯的,但如果去掉這個限制條件,就用上面的程式求解就會出錯。
那麼,如何求解序列s的最長非降子串行的長度(不要求以s的最後乙個元素作為lis的最大元素)?
這通常需要轉化為最長公共子串行(lcs)的問題。即:序列s的lis= 將s排序後的有序序列s' 與 原序列s 的最長公共子串行。
例如,s= 的lis為或,長度為3
對s排序後的s'=, s『與 s的最長公共子串行就是和
所以,如何求解序列s的最長非降子串行的長度,首先需要進行排序,然後求lcs的長度即可。
示例**:
publicstatic
void
main(stringargs)
int copy=peaches.clone();
quicksort(peaches,0,n-1);
int lislength=lcs(peaches,copy)
system.out.println("lis length is"+lislength);
}public
static
void quicksort(int arr,int start,int
end)
arr[i]=arr[j];
while(iarr[i])
arr[j]=arr[i];
}arr[i]=key;
quicksort(arr,start,i-1);
quicksort(arr,i+1,end);
}public
static
int lcs(inta,int
b) }
return
c[a.length][b.length];
}
如何求lcs的長度?看這裡
LIS 求最長遞增子串行
動態規劃,dp 時間複雜度 olog n 2 include include include include include using namespace std int lis int a,int alen,int len if alen i maxlen return maxlen int m...
最長遞增子串行 LIS
對於這個問題,最直觀的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...
最長遞增子串行 LIS
給定乙個長度為n的陣列,找出乙個最長的單調自增子序列 不一定連續,但是順序不能亂 例如 給定乙個長度為6的陣列a,則其最長的單調遞增子串行為,長度為4.這個問題可以轉換為最長公共子串行問題。如例子中的陣列a,則我們排序該陣列得到陣列a 然後找出陣列a和a 的最長公共子串行即可。顯然這裡最長公共子串行...