LIS(兩種方法求最長上升子序列)
阿新 • • 發佈:2018-10-02
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(兩種方法求最長上升子序列)