1. 程式人生 > >LIS(兩種方法求最長上升子序列)

LIS(兩種方法求最長上升子序列)

align 兩種 pca alt pre nlogn 規劃 序列 oca

首先得明白一個概念:子序列不一定是連續的,可以是斷開的。

有兩種寫法:

一、動態規劃寫法

復雜度:O(n^2)

代碼:

 1 #include <iostream>
 2 #include <queue>
 3 #include <cstdio>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <cstring>
 7 #define INF 0x3f3f3f3f
 8 
 9 using namespace std;
10 typedef long long ll;
11 const int maxn = 1000; 12 int a[maxn],dp[maxn]; 13 14 int main() 15 { 16 ios::sync_with_stdio(false); 17 int n; 18 while(cin>>n && n) 19 { 20 for(int i = 0; i<n; i++) 21 cin>>a[i]; 22 int mmax = -1; 23 for(int i = 0; i<n; i++)
24 { 25 dp[i] = 1; 26 for(int j = 0; j<i; j++)//遍歷之前的每一個元素pre 27 { 28 if(a[j]<a[i] && (dp[j]+1>dp[i]))//如果元素pre < 當前元素cur,而且pre的長度+1要比當前的長度多就更新當前的長度 29 { 30 dp[i] = dp[j]+1; 31 }
32 } 33 mmax = max(mmax,dp[i]);//維護最大的長度 34 } 35 printf("%d\n",mmax); 36 } 37 return 0; 38 }

二、low_bound寫法

復雜度:O(nlogn)

這種寫法就是將動規寫法中的第二層的遍歷改為了二分查找。所以復雜度變為O(nlogn)

牛客講解視頻

該算法中開了一個輔助數組h來表示該長度下最後的元素的最小值。例如 1、2、0、5 、-1

技術分享圖片技術分享圖片?

為什麽要修改h數組裏邊的數為小的值呢,因為修改後h數組能變長的潛力就增大了,所以要修改。

代碼:

 1 #include <iostream>
 2 #include <queue>
 3 #include <cstdio>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <cstring>
 7 #define INF 0x3f3f3f3f
 8 
 9 using namespace std;
10 typedef long long ll;
11 const int maxn = 1000;
12 int a[maxn],dp[maxn];
13 
14 int main()
15 {
16     ios::sync_with_stdio(false);
17     int n;
18     while(cin>>n)
19     {
20         memset(a,0,sizeof(a));
21         for(int i = 0; i<n; i++)
22             dp[i] = INF;
23         for(int i = 0; i<n; i++)
24             cin>>a[i];
25         int mmax = -1;
26         for(int i = 0; i<n; i++)
27         {
28             int k = lower_bound(dp, dp+n, a[i])-dp;
29             dp[k] = a[i];
30             mmax = max(mmax, k+1);
31         }
32         printf("%d\n",mmax);
33     }
34     return 0;
35 }

LIS(兩種方法求最長上升子序列)