方法一:
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 ...