您的位置:首页 > 其它

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

2016-11-26 20:46 190 查看
本文的讲解摘自《挑战程序设计竞赛》

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

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

定义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,,,,

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

提升:应用最长上升子序列!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: