问题描述:
在数字列A={a1,a2….an}中按递增下标序列顺序选出一个子序列B,如果B中的数严格递增,则序列B为A的递增子序列。现给你一个数字序列,求出他的最长递增子序列。(只要求下标递增,不要求连续)。
分析:
方法1:
用L[i]记录a1~ai的最长递增子序列的长度,初始值都为1。当求L[i]时,L[i]的值等于下标值j在i之前的(j小于i)且a[j]小于a[i]的L[j]+1的最大值。所以每次只用扫描a[1]~a[i-1]即可。用X[i][n]记录下标为a[i]的最长子序列。
方法2:
利用lower_bound(a,a+n,k)函数;lower_bound()函数的功能是在有序数组a中查找a[i]>=k的最小指针。在长度相等时,保存最后元素最小的值。
1:
#include <iostream>
using namespace std;
const int MAXN=1005;
int a[MAXN],L[MAXN],X[MAXN][MAXN];
int IncreaseOrder(int n);
int main()
{
int n,i;
cin>>n;
for(i=0;i<n;i++)
cin>>a[i];
cout<<IncreaseOrder(n)<<endl;
return 0;
}
int IncreaseOrder(int n)
{
int i,j,k,index;
for(i=0;i<n;i++)
{
L[i]=1;
}
for(i=1;i<n;i++)
{
int maxL = 1;
int dj;
for(j=i-1;j>=0;j--)
{
if(a[j]<a[i] && L[j]+1>maxL)
{
maxL=L[j]+1;
dj=j;
}
}
L[i] = maxL;
for(k=0;k<maxL-1;k++)
X[i][k] = X[dj][k];
X[i][maxL-1] = a[i];
}
index = 0;
for(i=1;i<n;i++)
if(L[i]>L[index])
index = i;
cout<<"最长递增子序列:"<<endl;
for(i=0;i<L[index];i++)
cout<<X[index][i]<<" ";
cout<<endl;
return L[index];
}
2:
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 10000;
const int INF = 9999999;
int dp[maxn],a[maxn],n;
void solve()
{
fill(dp,dp+n,INF);
for(int i=0;i<n;i++)
{
*lower_bound(dp,dp+n,a[i])=a[i];
}
cout<<(lower_bound(dp,dp+n,INF)-dp);
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
solve();
return 0;
}