lis nlogn

lis的nlogn算法
lis有一般的O(N^2)的dp算法:d[i]=max{0,d[j]|j<i,A(j)<A(i)}+1;其中d[i]为以第i个结尾的最长上升子序列。
比如1,3,2,4。d[4]=max{0,d[1],d[3],d[2]}+1(如果lis可以有相同的值,取<=)。
然而有些情况可能O(N^2)的dp算法速度不符合要求,便有了下面的nlogn算法。
首先给出代码,然后解释为什么:
for(int i=1; i<n;i++)    g[i]=INF;
for(int i=0; i<n; i++)
{
int v=lower_bound(g+1,g+n+1,A[i])-g;
d[i]=k;
g[k]=A[i];
}
A为原始序列。lower_bound()为二分查找。
首先,对于d[i]=d[j],如果A[i]<A[j]的话,对于后续情况,d[i]更有可能i更有可能取得最优解。比如1,5,2,4。取2而非取5。
因此,对于同样的d值,只保存A值最小的不会影响结果。于是就用g[i]保持长度为i的上升子序列的最小A值。比如:g[2]=2。还可以证明
g[]一定是非降的,g[1]<=g[2]<=g[3]....。这符合和二分查找的特点(nlogn)。


算法同样是从0到n更新d[]。但现在不是从0到i-1查找d[j]了。而是直接从g[]中找到大于A[i]的位置的后一位。而g的下标代表的是lis的长度。
现在v就是以第i个结尾的最长上升子序列的长度。为什么可以呢,因为第v个位置以前,都是A值小于A[j]的,相当于O(N^2)中的A(j)<A(i)(g[]的值是A值)
只是是同等长度最小的A[j]值。而且v-1就是以A[j]结尾的长度。


然后更新g[k]=A[i];为什么要这样呢。举例:1,2,4,3。i=2的时候g[3]=4,i=3的时候v=3,替换掉4为3。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值