问题描述
给你一个数列,请你找出该序列数字依次递增的子序列(注意子序列不要求数字相邻)。例如1、7、3、5、9、4、8。其中一次递增的子序列有(1、7),(1、3、5、9),(1、3、4、8)等,其中最长的长度为4。
输入描述
输入包含多组数据,每组数据第一行包含一个正整数n(1≤n≤1000)。
紧接着第二行包含n个正整数m(1≤n≤10000)。
输出描述
对应每一组数据,输出最长递增子序列的长度。
输入
7
1 7 3 5 9 4 8
6
1 3 5 2 4 6
输出
4
4
题解
O(n^2)算法
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int a[1005],dp[1005];
int n;
int LIS()
{
int i,j,ans,m;
dp[1]=1;
ans=1;
for(i=2;i<=n;i++){
m=0;
for(j=1;j<i;j++){
if(dp[j]>m&&a[j]<a[i])
m=dp[j];
}
dp[i]=m+1;
if(dp[i]>ans)
ans=dp[i];
}
return ans;
}
int main()
{
while(~scanf("%d",&n)){
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
printf("%d\n",LIS());
}
return 0;
}
O(nlogn)算法
只管维持一个最小的递增子序列即可。
#include <cstdio>
#include <iostream>
using namespace std;
int a[1005],dp[1005];
int n;
int main()
{
while(~scanf("%d",&n)){
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
dp[1]=a[1];
int len=1;
for(int i=2;i<=n;++i){
if(a[i]>dp[len])
dp[++len]=a[i];
else{
int pos=lower_bound(dp,dp+len,a[i])-dp;
dp[pos]=a[i];
}
}
printf("%d\n",len);
}
return 0;
}