LIS入门-2

前面我们已经简单的介绍了LIS,并学习了复杂度为O(n*n)的算法,但是因为它的复杂度有点高,所以有的时候会超时,在这里我们再学习一种复杂度为O(NlogN)的算法:

O(NlogN)做法:贪心+二分

我们还是举一个例子来描述一下这个过程,我们有一个序列a[]={1,7,3,5,9,4,8},再定义一个数组dp[];用Len来代表此时的LIS;

利用贪心的思想,对于一个上升子序列,显然当前最后一个元素越小,越有利于添加新的元素,这样LIS长度自然更长。

我们的dp就是用来存此时选中的数字,

在这里我们让a数组从1开始,

首先我们先来看a[1]。因为只有一个数字,所以我们把a[1]添加到dp中,此时dp[]={1};此时len=1;

然后看a[2],因为a[2]>a[1],所以此时我们把a[2]也添加到dp中,此时dp[]={1,7},len=2;

然后我们看a[3],我们从dp中找到那么第一个大于a[3]的数,如果找到,那么我们就把这个数字替换成a[3],此时dp[]={1,3},len还是等于2;如果找到不到呢,那么证明此时这个数字就是最大的,我们把它也添加到dp数组中,再把len=len+1;

再看a[4],我们再dp中找不到比a[4]大的数字,所以此时dp[]={1,3,5},len=len+1.

......................................

这就是大致的过程吧,但是有一个问题很容易错,那就是最后dp数组存的数并不是LIS的路径,至于为什么?在这里先不做解释,以为我也不会,哈哈;

在找dp中的比a[i]打的数中,其实我们没有必要一个一个的去找,我们可以用二分法,这个方相信大家都会吧。

如果让你用二分法你会怎么用?你是不是自己写一个函数,然后去用,其实没有必要这么麻烦,我们·可以直接调用一个函数

lower_bound(dp,dp+n,m)

这个函数里面有三个参数,第一个和第二个就是你要从哪找到哪,后面的m就是你要找的那个数字,

这个函数得返回值就是比m>=的那个数的位置·,也就相当于返回一个指针吧,

下面给出LIS O(NlogN)的模板:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=1e3+7;
const int MAX=0x3f3f3f3f;
int a[maxn];
int main()
{
    memset(a,MAX,sizeof(a));//先把数组的初值赋为最大。
    int n;
    scanf("%d",&n);
    int A;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&A);
        *lower_bound(a,a+n,A)=A;//用二分法
    }
    printf("%d\n",lower_bound(a,a+n,MAX)-a);
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值