最長上公升子串行的兩種解法

2022-04-27 11:45:57 字數 2366 閱讀 1131

問題描述

乙個數的序列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)等等。這些子串行中最長的長度是4,比如子串行(1, 3, 5, 8).

你的任務,就是對於給定的序列,求出最長上公升子串行的長度。

如何把這個問題分解成子問題呢?經過分析,發現 「求以ak(k=1, 2, 3…n)為終點的最長上公升子串行的長度」是個好的子問題――這裡把乙個上公升子串行中最右邊的那個數,稱為該子串行的「終點」。雖然這個子問題和原問題形式上並不完全一樣,但是只要這n個子問題都解決了,那麼這n個子問題的解中,最大的那個就是整個問題的解。

由上所述的子問題只和乙個變數相關,就是數字的位置。因此序列中數的位置k 就是「狀態」,而狀態 k 對應的「值」,就是以ak做為「終點」的最長上公升子串行的長度。這個問題的狀態一共有n個。狀態定義出來後,轉移方程就不難想了。假定maxlen (k)表示以ak做為「終點」的最長上公升子串行的長度,那麼:

maxlen (1) = 1

maxlen (k) = max

seqlen[i]=max+1;

if(seqlen[i]>maxlen) //seqlen中儲存的是第i個數為終點的最長上公升序列,找出這個陣列中最大的值即為最優序列長度

maxlen=seqlen[i];

} printf("%d/n",maxlen);

return 0;

}假設存在乙個序列d[1..9] = 2 1 5 3 6 4 8 9 7,可以看出來它的lis長度為5。n

下面一步一步試著找出它。

我們定義乙個序列b,然後令 i = 1 to 9 逐個考察這個序列。

此外,我們用乙個變數len來記錄現在最長算到多少了

首先,把d[1]有序地放到b裡,令b[1] = 2,就是說當只有1乙個數字2的時候,長度為1的lis的最小末尾是2。這時len=1

然後,把d[2]有序地放到b裡,令b[1] = 1,就是說長度為1的lis的最小末尾是1,d[1]=2已經沒用了,很容易理解吧。這時len=1

接著,d[3] = 5,d[3]>b[1],所以令b[1+1]=b[2]=d[3]=5,就是說長度為2的lis的最小末尾是5,很容易理解吧。這時候b[1..2] = 1, 5,len=2

再來,d[4] = 3,它正好加在1,5之間,放在1的位置顯然不合適,因為1小於3,長度為1的lis最小末尾應該是1,這樣很容易推知,長度為2的lis最小末尾是3,於是可以把5淘汰掉,這時候b[1..2] = 1, 3,len = 2

繼續,d[5] = 6,它在3後面,因為b[2] = 3, 而6在3後面,於是很容易可以推知b[3] = 6, 這時b[1..3] = 1, 3, 6,還是很容易理解吧? len = 3 了噢。

第6個, d[6] = 4,你看它在3和6之間,於是我們就可以把6替換掉,得到b[3] = 4。b[1..3] = 1, 3, 4, len繼續等於3

第7個, d[7] = 8,它很大,比4大,嗯。於是b[4] = 8。len變成4了

第8個, d[8] = 9,得到b[5] = 9,嗯。len繼續增大,到5了。

最後乙個, d[9] = 7,它在b[3] = 4和b[4] = 8之間,所以我們知道,最新的b[4] =7,b[1..5] = 1, 3, 4, 7, 9,len = 5。

於是我們知道了lis的長度為5。

!!!!! 注意。這個1,3,4,7,9不是lis,它只是儲存的對應長度lis的最小末尾。有了這個末尾,我們就可以乙個乙個地插入資料。雖然最後乙個d[9] = 7更新進去對於這組資料沒有什麼意義,但是如果後面再出現兩個數字 8 和 9,那麼就可以把8更新到d[5], 9更新到d[6],得出lis的長度為6。

然後應該發現一件事情了:在b中插入資料是有序的,而且是進行替換而不需要挪動——也就是說,我們可以使用二分查詢,將每乙個數字的插入時間優化到o(logn)~~~~~於是演算法的時間複雜度就降低到了o(nlogn)~!

#include #include#includeusing namespace std;

#define maxn 50010

typedef long long ll;

ll arr[maxn],ans[maxn],len;

int main()

ans[1]=arr[1];

len=1;

for(i=2;i<=p;i++)

}printf("%lld\n",len);

// }

return 0;

}

最長上公升子串行的兩種寫法

乙個序列a 找出它的最長上公升子串行的個數,很明顯是4個,可以是,或者。他有兩種實現的方法 第一種是時間複雜度為o n 2 的演算法 include include include include using namespace std intmain int n sizeof a sizeof i...

最長上公升子串行(Python and C 解法)

給定乙個無序的整數陣列,找到其中最長上公升子串行的長度。示例 輸入 10,9,2,5,3,7,101,18 輸出 4 解釋 最長的上公升子串行是 2,3,7,101 它的長度是 4。說明 子串行不同於子串,可以不連續。採用動態規劃。定義狀態 dp i 表示以 nums i 這個數為結尾的最長遞增子串...

最長上公升子串行(兩種方法)

設有整數序列b1,b2,b3,bm,若存在下標i1第一行n 第二行 整數序列 10318 7141012 2341 1624最大長度n和所有長度為n的序列個數 6把每個數與前面的數組成的最長上公升子串行的長度記錄在一維陣列中。記錄的數就是前面小於它的數中最長上公升子串行的長度最長的數 1。一下內容補...