定义
最长上升子序列(Longest Increasing Subsequence,LIS),在计算机科学上是指一个序列中最长的单调递增的子序列。
求解方法
求LIS一般有两种方法
O(n2) 算法
f[i] 表示以当前为序列的最后一位时所能达到的最LIS。
则有如下递推式:
f[i]=max(f[j]+1)(a[j]<a[i])
如果没找到则 f[i]=1 。
因为每个数都要从头扫一遍,因此时间复杂度为 O(n2) 。
伪代码( a[i] 存的是值):
ans=0; memset(f,0,sizeof(f)); f[1]=1;
for (int i=1;i<=n;i++){
for (int j=1;j<i;j++)
if (a[i]>a[j])//一定要满足这个条件
ans=max(ans,f[i]=max(f[i],f[j]+1));
ans=max(ans,f[i]=max(f[i],1));
}
printf("%d\n",ans);
return 0;
O(nlog2n) 算法
g[i]
表示LIS长度为
i
时
因为相同LIS的情况下,值越小更新的可能性越大。因此要存最小值。
对于枚举到的数
a[i]
,如果当前值比
g[t]
还大(
t
为目前已知LIS),那么直接放入
伪代码:
int srch(int v,int l,int r){//二分查找
while (l<=r){
int mid=(l+r)/2;
if (v>g[mid]) l=mid+1;
else r=mid-1;
}
return l;
}
······
g[1]=a[1]; t=1;
for (int i=2;i<=n;i++)
if (a[i]>g[t]) g[++t]=a[i];
else g[srch(a[i],1,t,true)]=a[i];
printf("%d\n",t)