转自:
http://blog.csdn.net/tianshuai1111/article/details/7887810
一,题目
求一个数组的最长递减子序列
比如{9,4,3,2,5,4,3,2}的最长递减子序列为{9,5,4,3,2}
求一个数组的最长递增子序列
比如{1,-1,2,-3,4,-5,6,-7}的最长递减子序列为{1,2,4,3,6}
二,递增序列长度求解方法
解法一:
时间复杂度为 o(n^2)
遍历数组序列,每遍历一个数组元素,则求序列到当前位置 最长的递增序列数,用temp[i]存储。
注意,当前的最长递增子序列受已经遍历的最长递增子序列影响,从序列头 再遍历到当前位置的前一个位置,挨个比较 a[j]与a[i](当前元素)大小,遇到小于a[i]且判断需要更新
temp[]数组。
由于这里仅仅是求,最长递增序列的长度,所以仅仅用temp[]存储长度大小。
源码:
解法二:时间复杂度任然为 O(n^2)
为了减少比较次数
采用空间换时间的策略。新增一个数组MaxV[],max[i]表示所有长度为i的递增子序列中最大值之间的最小值
nMaxlax记录当前最长子序列
每次遍历一个元素时候,从最长子序列开始遍历,一直到1 比较当前元素值arr[i] 跟MaxV[j]的值,从而更新temp[]最长子序列和nMaxLax和MaxV[]的值
源码:
解法三:
将内循环查询部分换成二分搜索,则时间复杂度降低为 O(nlogN)
解法四:
如5 1 6 8 2 4 5 10这一序列。
从第一个元素开始遍历,放到a数组中。即a[1]=5,接着遍历序列,第二个数是1 ,1<5 ,所以a[1]=1;
第三个数是6,6>1。所以a[2]=6。第四个数是8,8>1&&8>6,所以a[3]=8。第五个数是2 ,2>1&&2<6。所以a[2]=2......如此类推。最后a数组中存放的,就是最长的递增子序列。
例题:(https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1134)
第1行:1个数N,N为序列的长度(2 <= N <= 50000) 第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9)
输出最长递增子序列的长度。
8 5 1 6 8 2 4 5 10
5
//AC
#include<iostream>
#include<cstring>
using namespace std;
int a[100000];
int b[100000];
int c[100000];
int main()
{
int n,i,j;
while(cin>>n)
{
fill(b,b+n,1);
memset(c,0,sizeof(c));
for(int i=0;i<n;i++)
cin>>a[i];
//int maxx=-1;
c[0]=a[0];
int l=0;
for(int i=1;i<n;i++)
{
int z=0;
for(int j=0;j<=l;j++)
{
if(a[i]<c[j])
{
z=1;
c[j]=a[i];
break;
} //cout<<c[j]<<" ";
}
if(!z)
{
l++;
c[l]=a[i];
}
//cout<<endl;
}
/*for(int i=0;i<=l;i++)
cout<<c[i]<<" ";
cout<<endl;*/
cout<<l+1<<endl;
//cout<<maxx<<endl;
}
return 0;
}
三,递减序列 最长子序列求解方法
用index数组,从大到小排序。然后依次遍历元素,查找元素在index数组中的位置pos ,根据位置来判断当前最长的子序列。