最長上公升子串行 LIS 的貪心演算法

2021-10-18 17:38:48 字數 2688 閱讀 9294

我們知道通過dp的演算法可以求出一段序列的最長上公升子串行,時間複雜度為o(n^2)。下面來介紹一種o(nlogn)的演算法來求lis。

設一段序列的長度為n,我們需要的是乙個輔助陣列f,長度最長為n,其實際長度是動態的,也表徵了最長上公升子串行的長度。

對於f[i],其儲存的是對於已經掃瞄過的序列中,所有長度為i上公升子串行的最後乙個數的最小值。如:

有序列1 4 2 3

所有長度為2的上公升子串行有1 2,1 3.

那麼f[2] = 2

這樣做,可以保證對於同樣長度的上公升子串行,我們給出的是其尾元素的最小值,那麼這樣在掃瞄後續序列時,就必定更有可能構造出最長上公升子串行。

首先可以證明整個f陣列是單調遞增的,即對於任意的索引i < j,都有f[i] < f[j]。反證法如下:

f[i] == f[j],對於f[j]對應的長度為j的最長上公升子串行,其倒數第2個元素值一定小於f[j],那麼這個倒數第2個元素值可以作為f[i],則有f[i] < f[j]

同理可證f[i] > f[j]的情形。

繼續分析:

如已掃瞄序列1 4 2 3,根據我們的定義,有f[3] = 3(序列1 2 3的尾元素),再往後掃瞄時,如果是4,即序列為1 4 2 3 4時,就可以根據f[3] = 3(3 < 4)往後延長乙個lis長度(即f長度變為4),而且使得f[4] = 4(即1 2 3 4的尾元素)。這樣顯然是合理的,而且可以為以後lis長度的更新以及尾元素的更新做鋪墊。

或者從反面考慮:如果我們f[i]儲存的不是長度為i的最長上公升子串行的尾元素,如f[3] = 5(存1 4 5的尾元素),那麼掃瞄後續元素就無法最大化地延長上公升序列,無法達到題目要求。

注意在思考問題時,從集合的角度考慮問題,即每個f[i]首先是關於所有長度為i的上公升序列的函式,其次,f[i]存的是這些上公升序列尾元素的最小值。

那麼在掃瞄原陣列的時候,對於第i個數,可以根據前i-1個數得到的f陣列的結果,對f陣列進行長度或內容的更新,具體表現如下:(設f陣列的實際長度為cnt

1、若a[i] > f[cnt],則對於從1至cntf中的每乙個f[j],都有a[i] > f[j](因為前面已經證明f單調遞增)。那麼當前的a[i]可以作為長度為cnt+1的上公升子串行的最小元素(因為當前只有這麼乙個長度為cnt+1的上公升序列),即f[cnt+1] = a[i],同時cnt++.

2、若a[i] <= f[cnt],則無法使得上公升序列變長,因為f[cnt]是長度為cnt的所有上公升序列尾元素的最小值。因此,它的作用是,更新對應的乙個f。顯然,對於從後往前第乙個小於a[i]f[j]而言,a[i]可以接到f[j]所代表的那個最優上公升序列後面,從而更新f[j+1](長度為j+1的上公升序列的尾元素最小值)。因為從剛才的敘述可以知道,原f[j+1] >= a[i]。故這樣a[i]的作用是直接改變f的乙個恰當元素值,同時為最終cnt的更新作準備(通過將乙個f的元素值變小,使得後面元素接到前面更具有可能)。

ac**:

#include

#include

#include

#include

#include

using

namespace std;

const

int n =

1e5+5;

int n;

int a[n]

,f[n]

;int cnt =0;

intfind

(int x)

return l;

}int

main()

f[++cnt]

= a[1]

;for

(int i =

2;i <= n;i++

)printf

("%d\n"

,cnt)

;return0;

}

貪心演算法之 最長上公升子串行

題目描述 給定乙個整型陣列,求這個陣列的最長嚴格遞增子串行的長度。譬如序列1 2 2 4 3 的最長嚴格遞增子串行為1,2,4或1,2,3.他們的長度為3。輸入 輸入可能包含多個測試案例。對於每個測試案例,輸入的第一行為乙個整數n 1 n 100000 代表將要輸入的序列長度 輸入的第二行包括n個整...

最長上公升子串行 LIS 演算法

開乙個棧,每次取棧頂元素top和讀到的元素temp做比較,如果temp top 則將temp入棧 如果temp top則二分查詢棧中的比temp大的第1個數,並用temp替換它。最長序列長度即為棧的大小top。這也是很好理解的,對於x和y,如果x y且stack y stack x 用stack x...

最長上公升子串行 LIS

題目 兩道題幾乎一樣,只不過對於輸入輸出的要求有所不同罷了。lis有兩種方法 一 第一種方法 時間複雜度為o n 2 狀態 dp i 區間為0 i的序列的lis 轉移方程 dp i max 1,dp k 1 0 k include include include include using name...