最长递增子序列
时间复杂度为o(n^2):
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
using namespace std;
int a[100]= {0};
int dp[100]= {0};
int main()
{
int i,j,n,m;
scanf("%d",&m);
while(m--)
{
scanf("%d",&n);
for(i=0; i<n; i++)
dp[i]=1;
for( i=0; i<n; i++)
scanf("%d",&a[i]);
for( j=1; j<n; j++)
{
for( i=0; i<j; i++)
{
if(a[i]<a[j])
{
dp[j]=max(dp[i]+1,dp[j]);
}
}
}
sort(dp,dp+n);
printf("%d\n",dp[n-1]);
}
return 0;
}
时间复杂度为o(nlogn)
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f3f
const int maxn=100005;
int A[maxn];
int F[maxn];//表示到当前位置的最长子序列长度;
int D[maxn];//用来二分的,存的数值并不是符合题意的单增子序列;
//D数组最多用(最长子序列长度)个空间;
int main()
{
int n,i;
while(scanf("%d",&n)!=EOF)
{
for(int i=1; i<=n; i++)
scanf("%d",&A[i]);
for(i=1; i<=n; i++)
D[i]=INF;
int max_len = 0; //初始化一个记录单增子序列长度的变量;
D[++max_len] = A[1];
F[1] = max_len;
for(int i = 2; i <= n; i++)
{
if(D[max_len] < A[i])
{
D[++max_len] =A[i];
F[i] = max_len;
}
else
{
int k = lower_bound(D+1, D+1+max_len, A[i]) - D;
D[k] = A[i];
F[i] = k;
}
}
cout<<max_len<<endl;
for(int i = n; i >= 1; i--) //逆输出单增系序列的元素;
{
if(F[i] == max_len)
{
printf("%d", A[i]);
if(max_len > 1) printf(" ");
max_len--;
}
}
}
return 0;
}
模拟一组数据加深印象;
8
1 7 6 8 3 2 6 5
D[ ]数组最多用(最长子序列长度)个空间;
F[ ]数组存的是到这个点目前最长子序列的长度;
lower_bound(a,a+n,x)-a:找到第一个大于等于 x 的下标;
upper_bound(a,a+n,x)-a:找到第一个大于 x 的下标;