最长上升子序列有好几种解法,这里介绍其中比较常用的两种。
第一种是普通的动态规划,时间复杂度为O(N^2),所以写一些数据比较大的题目就会超时,比如请看这题,没什么好说的,直接上代码。
#include
using namespace std;
int a[10],d[10],n;
int LIS(int *a,int n)
{
int maxs=1,i,j;
for(i=2;i<=n;i++)
{
for(j=1;j
a[j]&&d[j]>m) //如果下一个元素大于上一个元素,则d[i]=max(d[j]+1,d[i])
d[i]=d[j]+1;
}
if(d[i]>maxs) //d[i]中存储的是1-i中最长递增序列
maxs=d[i];
}
return maxs;
}
int main()
{
cin>>n;
for(int i(1);i<=n;i++)
cin>>a[i];
int len=LIS(a,n);
cout<
<
第二种是动态规划加二分查找,我们知道二分查找适用于大量查找而不适用于移动数据,这种方法正是用元素替换(即新来的满足条件的元素替换当前的元素)的技巧,巧妙利用了二分查找的这一特点,在普通动态规划的基础上利用二分查找将时间复杂度降低为O(N*logN),注释写在代码中。
#include
#define MAXN 1000
using namespace std;
int a[MAXN],d[MAXN],n;
int Binsearch(int key,int *d,int l,int r) //二分查找函数
{
while(l<=r)
{
int mid=(l+r)>>1; //利用了位运算,相当于mid=(l+r)/2
if(key>d[mid] && key
d[mid])
r=mid+1;
else
l=mid-1;
}
}
int LIS(int *a,int n)
{
int len=1,i,j;
d[1]=a[1];
for(i=2;i<=n;i++)
{
if(a[i]>d[len]) //如果a[i]>d[len],直接将a[i]加到数组d的后面,同时len++;
{
len++;
d[len]=a[i];
}
else //如果a[i]
>n;
for(int i(1);i<=n;i++)
cin>>a[i];
int len=LIS(a,n);
cout<
<