最長遞增子序列(兩種時間複雜度演算法及其區別)+最長遞減子序列(reverse)
阿新 • • 發佈:2019-01-11
O(n*n)
//LIS+路徑回溯 O(n*n) #include <iostream> #include<cstdio> #include<stack> #include<cstring> using namespace std; const int maxn=100+5; int a[maxn],dp[maxn]; int parent[maxn]; int main() { int n; while(scanf("%d",&n)==1&&n) { for(int i=0;i<n;i++) { scanf("%d",&a[i]); dp[i]=1; } memset(parent,-1,sizeof(parent)); int res=0,ans; for(int i=0;i<n;i++) for(int j=0;j<i;j++) if(a[j]<a[i]) { if(dp[j]+1>dp[i]) { parent[i]=j; dp[i]=dp[j]+1; } if(dp[i]>res) { ans=i; res=dp[i]; } } cout<<res<<endl; //LIS長度 stack<int>s; s.push(a[ans]); int p=parent[ans]; while(true) { s.push(a[p]); p=parent[p]; if(p==-1) break; } while(!s.empty()) { cout<<s.top()<<" "; s.pop(); } cout<<endl; } return 0; }
O(nlogn)
//最長遞增子序列 O(nlogn) #include <iostream> #include<cstdio> #include<algorithm> using namespace std; const int maxn=50000+5; const int INF=1e9+6; int a[maxn],dp[maxn]; int main() { int n; while(scanf("%d",&n)==1&&n) { for(int i=0;i<n;i++) { scanf("%d",&a[i]); dp[i]=INF; } for(int i=0;i<n;i++) { int p=lower_bound(dp,dp+n,a[i])-dp; dp[p]=a[i]; } cout<<lower_bound(dp,dp+n,INF)-dp<<endl; } return 0; }
注意:當使用較小時間複雜度的演算法時進行路徑回溯,結果可能並不正確,但最長遞增子序列的長度結果是正確的
當要求的為最長遞減子序列時,把原陣列進行反轉(reverse)操作,然後按照最長遞增子序列的方法求解即可