最长上升子序列两种复杂度的算法 LIS

本文的讲解摘自《挑战程序设计竞赛》

不过说实话最长上升子序列这个概念并不难,我觉得难的是你能够把题目中的意思和解法抽象成最长上升子序列

废话不多说了开始讲解第一种算法

定义dp[i] 表示以ai结尾的最长上升子序列的长度

这时呢又分为两种情况

第一只包含ai

第二 前面的长度 + ai

所以得到递推式

dp[i] = max(1,dp[j] + 1);

代码如下:

void solve()
{
    int res = 0;
    int i,j;
    for( i = 0;i < n;i++)
    {
        dp[i] = 1;    //最长上升子序列只有他自己,所以长度为1
        for(j = 0;j < i;j++)
        {

                  if(a[j] < a[i])                    //只有j下标的a小于i下标的a 才能构成上升子序列

                dp[i] = max(dp[i],dp[j] + 1);  //从0开始到当前的i中
        }
        res = max(res,dp[i]);    //挑选最大的上升子序列
    }
    cout<<res<<endl;
}

这种算法的复杂度是o(n^2)  太大了 一般不能满足题目的解题需求

所以再给出 o(nlog(n))复杂度的算法

下图为他的思想步骤


当长度相同时每次都找最小的值放在最后因为这样在以后的查找中更有优势

代码如下  这时利用了 STL中的一个函数

void solve()
{
    int i,j;
    int dp[10000];
    for(i = 0;i < n;i++)
    dp[i] = INF;
    for( i = 0;i < n;i++)
    {
       *lower_bound(dp,dp+n,a[i]) = a[i];
    }
    cout<<lower_bound(dp,dp+n,INF) - dp<<endl;
}



最后可以留一个简单的题目:

   给定你一组任意的数字  这组数字使乱序的 比如  1,32,12,34,0,21,324,21,,,,

请你找出如何删除最少的数字让剩下的数字有序?



提升:应用最长上升子序列!




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值