LIS(最長上公升子串行)

2021-09-10 10:32:15 字數 1651 閱讀 5108

方法一:

dp動態規劃

狀態設計:dp[i]代表以a[i]結尾的lis的長度 

狀態轉移:dp[i]=max(dp[i], dp[j]+1) (0<=j< i, a[j]< a[i]) 

時間複雜度:o(n^2) 

例題:

方法二:貪心+二分

時間複雜度nlog(n)

a[i]表示第i個資料。 

dp[i]表示表示長度為i+1的lis結尾元素的最小值。 

利用貪心的思想,對於乙個上公升子串行,顯然當前最後乙個元素越小,越有利於新增新的元素,這樣lis長度自然更長。 

因此,我們只需要維護dp陣列,其表示的就是長度為i+1的lis結尾元素的最小值,保證每一位都是最小值,這樣子dp陣列的長度就是lis的長度。

dp陣列具體維護過程同樣舉例講解更為清晰。 

同樣對於序列 a(1, 7, 3, 5, 9, 4, 8),dp的變化過程如下:

dp[0] = a[0] = 1,長度為1的lis結尾元素的最小值自然沒得挑,就是第乙個數。 (dp = )

對於a[1]=7,a[1]>dp[0],因此直接新增到dp尾,dp[1]=a[1]。(dp = )

對於a[2]=3,dp[0]< a[2]< dp[1],因此a[2]替換dp[1],令dp[1]=a[2],因為長度為2的lis,結尾元素自然是3好過於7,因為越小這樣有利於後續新增新元素。 (dp = )

對於a[3]=5,a[3]>dp[1],因此直接新增到dp尾,dp[2]=a[3]。 (dp = )

對於a[4]=9,a[4]>dp[2],因此同樣直接新增到dp尾,dp[3]=a[9]。 (dp = )

對於a[5]=4,dp[1]< a[5]< dp[2],因此a[5]替換值為5的dp[2],因此長度為3的lis,結尾元素為4會比5好,越小越好嘛。(dp = )

對於a[6]=8,dp[2]< a[6]< dp[3],同理a[6]替換值為9的dp[3],道理你懂。 (dp = )

ok,這樣子dp陣列就維護完畢,所求lis長度就是dp陣列長度4。 

通過上述求解,可以發現dp陣列是單調遞增的,因此對於每乙個a[i],先判斷是否可以直接插入到dp陣列尾部,即比較其與dp陣列的最大值即最後一位;如果不可以,則找出dp中第乙個大於等於a[i]的位置,用a[i]替換之。 

這個過程可以利用二分查詢,因此查詢時間複雜度為o(logn),所以總的時間複雜度為o(nlogn)

例題:lis 是最長上公升子串行。什麼是最長上公升子串行? 就是給你乙個序列,請你在其中求出一段最長嚴格上公升的部分,它不一定要連續。

就像這樣:2, 3, 4, 7 和 2, 3, 4, 6 就是序列 2 5 3 4 1  7  6 的兩個上公升子串行,最長的長度是 4。

#include using namespace std;

const int n = 1e5 + 9;

int f[n], a[n];

int n;

int find(int l, int r, int x)

else

} return l;

}int lis()

} return len;

}int main()

printf("%d\n", lis());

return 0;

}

最長上公升子串行 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...

最長上公升子串行LIS

問題 給定n個整數a1,a2,a3,a4,a5,an,從左到右的順序盡量選出多個整數,組成乙個上公升子串行,相鄰元素不相等。例如 1,6,2,3,7,5,它的最長上公升子串行為 1,2,3,5。分析 剛開始想這個問題的時候我想用遞迴來解決問題,可是後來考慮到遞迴的時間複雜度高,就覺得不能使用,並且本...

LIS 最長上公升子串行

最長遞增子串行問題 在一列數中尋找一些數,這些數滿足 任意兩個數a i 和a j 若i 設dp i 表示以i為結尾的最長遞增子串行的長度,則狀態轉移方程為 dp i max,1 j 這樣簡單的複雜度為o n 2 其實還有更好的方法。考慮兩個數a x 和a y x 按dp t k來分類,只需保留dp ...