您的位置:首页 > 其它

最长递增子序列(两种时间复杂度算法及其区别)+最长递减子序列(reverse)

2018-03-02 17:43 543 查看
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)操作,然后按照最长递增子序列的方法求解即可
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 dp LIS