最長單調遞增子串行

2021-06-09 22:25:57 字數 1858 閱讀 7816

單調子串行包含有單調遞增子串行和遞減子串行,不失一般性,這裡只討論單調遞增子串行。首先,從定義上明確我們的問題。給定序列a1, a2, …, an,如果存在滿足下列條件的子串行

ai1<=ai2

<=…<=aim, (其中i1即稱為乙個原序列的長度為m的單調遞增子串行,那麼,現在的問題是我們要找出乙個序列的最長的單調遞增子串行。

直觀上來說,乙個序列sn,它有2n個子序列,列舉所有的子串行,找出其中單調遞增的序列,然後返回其中最長的,這樣我們的問題就解決了。當然,這個直觀的演算法在時間上為o(2n*n),它的複雜度增長太快了,所以,我們還應該做得更好一些。

於是,我們換個角度思考。假設我們對sn排序(遞增),得到sn』。那麼,sn和sn』的最長公共子串行cm就是我們要求的最長單調遞增子串行(如果你不清楚最長公共子串行的定義,just google it)。為什麼?假設cm』是sn的最長單調子列,且cm』!=cm, cm』的長度大於cm。由於cm』是遞增的,並且cm』的每乙個元素都來自sn,所以cm』一定是sn』的子列,而cm』又是sn的子列,所以cm』是sn和sn』的公共子列,故cm』的長度一定小於cm,這與假設矛盾,所以cm是最長單調子列。理論上我們的演算法是正確的,複雜度方面,運用動態規劃(dynamic programming)來求解lcs(最長公共子列,longest-common-subsequence),時間上是o(n2),空間上也是o(n2)。於是,對sn排序需要nlogn的時間,而lcs需要n2,最後,我們的演算法時間上是o(n2)。

可以看到,通過上面的改進,我們的演算法效率得到了很大的提公升(從指數增長到多項式增長)。不過,程式設計的樂趣就是它會不斷地給我們一些驚喜,所以,就此打住不是我們該做的,於是,更好的演算法應該是存在的。

對於序列sn,考慮其長度為i的單調子列(1<=i<=m),這樣的子列可能有多個。我們選取這些子列的結尾元素(子列的最後乙個元素)的最小值。用li表示。易知

l1<=l2

<=…<=lm

如果li>lj(ij結尾的遞增子串行的最後j-i個元素,得到乙個長度為i的子串行,該序列的結尾元素ak

<=lj

i,這與li標識了長度為i的遞增子串行的最小結尾元素相矛盾,於是證明了上述結論。現在,我們來尋找sn對應的l序列,如果我們找到的最大的li是lm,那麼m就是最大單調子列的長度。下面的方法可以用來維護l。

從左至右掃瞄sn,對於每乙個ai,它可能

(1)    ai

1,那麼l1=ai

(2)    ai>=lm,那麼lm+1=ai,m=m+1 (其中m是當前見到的最大的l下標)

(3)    ls

<=ai

s+1,那麼ls+1=ai

掃瞄完成後,我們也就得到了最長遞增子串行的長度。從上述方法可知,對於每乙個元素,我們需要對l進行查詢操作,由於l有序,所以這個操作為logn,於是總的複雜度為o(nlogn)。優於開始o(n2)的演算法。這裡給出我的乙個實現:(演算法並沒有返回具體的序列,只是返回長度)

#include #include using namespace std;

void outputarray( int * data, int len)

} if( low == size )

return -1;

else

return low;

}template int lms (const t * data, int size, t* &s)

else //其他情況

s[index] = e;

}return s_count;

}int main()

; //int data[3] =;

//heapsort(data, 9);

outputarray(data, 12);

cout <

另:最長單調子串行及其計數問題

最長單調遞增子串行

設計乙個o n2 時間的演算法,找出由n個數組成的序列的最長單調遞增子串行。輸入 第1個整數n 0分析 用陣列b 0 i 記錄以a i 0 i a k 並且 b k max b j 1 j i 1 所以 b i b k 1.如果存在k b k b k 並且 a i a k 即 b i 不是滿足條件的...

最長單調遞增子串行問題

設計乙個o n2 複雜度的演算法,找出由n個數組成的序列的最長單調遞增子串行。public class lis 儲存資料 int b new int a.length 儲存每個元素的最長單調遞增子串行 int ab new int a.length a.length 儲存每個元素的單調遞增子串行值 ...

求最長單調遞增子串行

問題描述 設計乙個時間的演算法,找出由n個數組成的最長單調遞增子串行。演算法描述 演算法實現 includestruct date void ascorder struct date a,int n 輸出最長單調遞增子串行 找到最長單調遞增子串行開始的單元 int max 0 intfore for...