這題目是經典的dp題目,也可叫作lis(longest increasing subsequence)最長上公升子串行 或者 最長不下降子串行。很基礎的題目,有兩種演算法,複雜度分別為o(n*logn)和o(n^2) 。
a.o(n^2)演算法分析如下:
(a[1]...a[n] 存的都是輸入的數)
1、對於a[n]來說,由於它是最後乙個數,所以當從a[n]開始查詢時,只存在長度為1的不下降子串行;
2、若從a[n-1]開始查詢,則存在下面的兩種可能性:
(1)若a[n-1] < a[n] 則存在長度為2的不下降子串行 a[n-1],a[n];
(2)若a[n-1] > a[n] 則存在長度為1的不下降子串行 a[n-1]或者a[n]。
3、一般若從a[t]開始,此時最長不下降子串行應該是按下列方法求出的:
在a[t+1],a[t+2],...a[n]中,找出乙個比a[t]大的且最長的不下降子串行,作為它的後繼。
4、為演算法上的需要,定義乙個陣列:
int d[n][3];
d[t][0]表示a[t];
d[t][1]表示從i位置到達n的最長不下降子串行的長度;
d[t][2]表示從i位置開始最長不下降子串行的下乙個位置。
實現**如下:
#include using namespace std;
int main(void)
for(max=i=0;imax)
max=b[i];
cout<
顯然,這種方法的時間複雜度仍為o(n^2);
b.最長不下降子串行的o(nlogn)演算法分析如下:
設 a[t]表示序列中的第t個數,f[t]表示從1到t這一段中以t結尾的最長上公升子串行的長度,初始時設f [t] = 0(t = 1, 2, ..., len(a))。則有動態規劃方程:f[t] = max (j = 1, 2, ..., t - 1, 且a[j] < a[t])。
現在,我們仔細考慮計算f[t]時的情況。假設有兩個元素a[x]和a[y],滿足
(1)x < y < t
(2)a[x] < a[y] < a[t]
(3)f[x] = f[y]
此時,選擇f[x]和選擇f[y]都可以得到同樣的f[t]值,那麼,在最長上公升子串行的這個位置中,應該選擇a[x]還是應該選擇a[y]呢?
很明顯,選擇a[x]比選擇a[y]要好。因為由於條件(2),在a[x+1] ... a[t-1]這一段中,如果存在a[z],a[x] < a[z] < a[y],則與選擇a[y]相比,將會得到更長的上公升子串行。
再根據條件(3),我們會得到乙個啟示:根據f的值進行分類。對於f的每乙個取值k,我們只需要保留滿足f[t] = k的所有a[t]中的最小值。設d[k]記錄這個值,即d[k] = min (f[t] = k)。
注意到d的兩個特點:
(1) d[k]的值是在整個計算過程中是單調不下降的。
(2) d的值是有序的,即d[1] < d[2] < d[3] < ... < d[n]。
利 用d,我們可以得到另外一種計算最長上公升子串行長度的方法。設當前已經求出的最長上公升子串行長度為len。先判斷a[t]與d[len]。若a [t] > d[len],則將a[t]接在d[len]後將得到乙個更長的上公升子串行,len = len + 1, d[len] = a [t];否則,在d[1]..d[len]中,找到最大的j,滿足d[j] < a[t]。令k = j + 1,則有a [t] <= d[k],將a[t]接在d[j]後將得到乙個更長的上公升子串行,更新d[k] = a[t]。最後,len即為所要求的最長上 公升子串行的長度。
在 上述演算法中,若使用樸素的順序查詢在d[1]..d[len]查詢,由於共有o(n)個元素需要計算,每次計算時的複雜度是o(n),則整個演算法的 時間複雜度為o(n^2),與原來的演算法相比沒有任何進步。但是由於d的特點(2),我們在d中查詢時,可以使用二分查詢高效地完成,則整個演算法 的時間複雜度下降為o(nlogn),有了非常顯著的提高。需要注意的是,d在演算法結束後記錄的並不是乙個符合題意的最長上公升子串行!
#include using namespace std;
int find(int *a,int len,int n)//若返回值為x,則a[x]>=n>a[x-1]
cout<}
return 0;
}
最長上公升子串行nlogn演算法
這題目是經典的dp題目,也可叫作lis longest increasing subsequence 最長上公升子串行 或者 最長不下降子串行。很基礎的題目,有兩種演算法,複雜度分別為o n logn 和o n 2 a.o n 2 演算法分析如下 a 1 a n 存的都是輸入的數 1 對於a n 來...
最長上公升子串行nlogn演算法
定義d k 長度為k的上公升子串行的最末元素,若有多個長度為k的上公升子串行,則記錄最小的那個最末元素。注意d中元素是單調遞增的,下面要用到這個性質。首先len 1,d 1 a 1 然後對a i 若a i d len 那麼len d len a i 否則,我們要從d 1 到d len 1 中找到乙個...
最長上公升子串行nlogn演算法
剛才用o n 2 的dp演算法做了最長上公升子串行,具體見poj2533解題報告。後來在網上看到說lis問題有o nlogn 的演算法,於是拿來小研究了一下。這個演算法其實已經不是dp了,有點像貪心。至於複雜度降低其實是因為這個演算法裡面用到了二分搜尋。本來有n個數要處理是o n 每次計算要查詢n次...