LIS(基于贪心的O(NlogN)解法)
LIS:最長上升子序列,常規的dp解法,時間復雜度為O(N^2)
常規解法傳送門:https://blog.csdn.net/tb_youth/article/details/89354053
下面我要介紹的是更快的解法:
前提是不需要輸出這個最長子序列,只需確定最長子序列的長度;
解釋:
基于貪心策略,為了得到一個最長的上升子序列,前面的數越小,對后面上升子序列的長度就越有利
只需要模擬一個棧,最終結果為棧的長度,先把第一個元素壓入棧,對于后面的元素,只需要 先比較棧頂元素,如果比棧頂元素大就直接壓入棧,否則,在棧中 二分查找 第一個 比此時這個元素 大的元素,將 這個元素位置上的值 替換為 當前元素值,替換這一步就使前面的元素更小了,替換位置前的數沒有影響,替換位置上的數替換為當前數明顯是有利于后面上升子序列的增長(判斷當前元素時,棧內元素都是在此元素前面的)。
舉個栗子:
對于 (3, 1,3, 2,5,1, 6)
棧s:(為了方便從是s[1]開始,如果從s[0]開始,最終結果要+1)
先把第1個元素壓入棧,s[1] = 3;
從第2個元素1開始:
棧頂:s[1]
1 < s[1]
在棧中s(3),查找第一個大于它的元素:
此時找到的為s[1]
替換:s[1] = 1
棧中變為s(1)
(這里可以明顯看出更小的在前面更有利嘛)
第3個元素3:
3 > s[1]
直接壓棧s[2] = 3
棧頂更新為s[2],
s(1,3)
第4個元素2:
2 < s[2]
在棧中s(1,3)找第一個大于它的數,
找到的為s[2]
s[2]替換,s[2] = 2
棧中變為:s(1,2)
繼續:
第五個元素5
5 > s[2]
直接壓入,s[3] = 5
s(1,2,5)
第六個元素1
1 < s[3]
在棧中s(1,2,5)查找第一個大于它的數s:
查到為s[2]
s[2] = 1
棧中變為:s(1,1,5)
第七個元素6,
6 > s[3]
直接壓入棧,s(1,1,5,6)
結束。
最終在棧中的元素雖然不是對應的最長子序列,
但是我們每一步操作都讓我們后面增長遞增子序列更有利。
所以最終的長度一定是ans.
長度為4,ans = 4
代碼:
總結
以上是生活随笔為你收集整理的LIS(基于贪心的O(NlogN)解法)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: P1119 灾后重建(经典floyd)
- 下一篇: P1886 滑动窗口(求连续区间最值的O