单调子序列包含有单调递增子序列和递减子序列,不失一般性,这里只讨论单调递增子序列。首先,从定义上明确我们的问题。给定序列a1, a2, …, an,如果存在满足下列条件的子序列

ai1<=ai2<=…<=aim, (其中i1<i2<…<im)

即称为一个原序列的长度为m的单调递增子序列,那么,现在的问题是我们要找出一个序列的最长的单调递增子序列。
 
直观上来说,一个序列Sn,它有2n个子序列,枚举所有的子序列,找出其中单调递增的序列,然后返回其中最长的,这样我们的问题就解决了。当然,这个直观的算法在时间上为O(2n*n),它的复杂度增长太快了,所以,我们还应该做得更好一些。
 
于是,我们换个角度思考。假设我们对Sn排序(递增),得到Sn’。那么,Sn和Sn’的最长公共子序列Cm就是我们要求的最长单调递增子序列(如果你不清楚最长公共子序列的定义,just google it)。为什么?假设Cm’是Sn的最长单调子列,且Cm’!=Cm, Cm’的长度大于Cm。由于Cm’是递增的,并且Cm’的每一个元素都来自Sn,所以Cm’一定是Sn’的子列,而Cm’又是Sn的子列,所以Cm’是Sn和Sn’的公共子列,故Cm’的长度一定小于Cm,这与假设矛盾,所以Cm是最长单调子列。理论上我们的算法是正确的,复杂度方面,运用动态规划(dynamic programming)来求解LCS(最长公共子列,Longest-Common-Subsequence),时间上是O(n2),空间上也是O(n2)。于是,对Sn排序需要nlogn的时间,而LCS需要n2,最后,我们的算法时间上是O(n2)。
 
可以看到,通过上面的改进,我们的算法效率得到了很大的提升(从指数增长到多项式增长)。不过,程序设计的乐趣就是它会不断地给我们一些惊喜,所以,就此打住不是我们该做的,于是,更好的算法应该是存在的。
 
对于序列Sn,考虑其长度为i的单调子列(1<=i<=m),这样的子列可能有多个。我们选取这些子列的结尾元素(子列的最后一个元素)的最小值。用Li表示。易知
L1<=L2<=…<=Lm
如果Li>Lj(i<j),那么去掉以Lj结尾的递增子序列的最后j-i个元素,得到一个长度为i的子序列,该序列的结尾元素ak<=Lj<Li,这与Li标识了长度为i的递增子序列的最小结尾元素相矛盾,于是证明了上述结论。现在,我们来寻找Sn对应的L序列,如果我们找到的最大的Li是Lm,那么m就是最大单调子列的长度。下面的方法可以用来维护L。
 
从左至右扫描Sn,对于每一个ai,它可能
(1)    ai<L1,那么L1=ai
(2)    ai>=Lm,那么Lm+1=ai,m=m+1 (其中m是当前见到的最大的L下标)
(3)    Ls<=ai<Ls+1,那么Ls+1=ai
 
扫描完成后,我们也就得到了最长递增子序列的长度。从上述方法可知,对于每一个元素,我们需要对L进行查找操作,由于L有序,所以这个操作为logn,于是总的复杂度为O(nlogn)。优于开始O(n2)的算法。这里给出我的一个实现:(算法并没有返回具体的序列,只是返回长度)
template <typename T>
int LMS (const T * data, int size)
...{
    if (size <= 0)
        return 0;

T * S = new T[size];
    int S_Count = 1;
    S[0] = data[0];

for (int i = 1; i < size; i++)
    ...{
        const T & e = data[i];
        int low = 0, high = S_Count - 1;
        
        while (low <= high)
        ...{
            int mid = (low + high) / 2;

if (S[mid] == e)
                break;
            else if (S[mid] > e)
            ...{
                high = mid - 1;
            }
            else
            ...{
                low = mid + 1;
            }
        }

//well, in this point
        //high is -1, indicating e is the smallest element.
        //otherwise, high indicates index of the largest element that is smaller than e
        if (high == S_Count - 1)
            S[S_Count++] = e;
        else
            S[high + 1] = e;
    }

return S_Count;
}

转自 http://skynewborn.blog.sohu.com/66594610.html

最长递增子序列O(nlogn)和O(n2)相关推荐

  1. 最长递增子序列 O(NlogN)算法

    最长递增子序列 O(NlogN)算法 今天回顾WOJ1398,发现了这个当时没有理解透彻的算法. 看了好久好久,现在终于想明白了. 试着把它写下来,让自己更明白. 最长递增子序列,Longest In ...

  2. 最长上升子序列 java_最长上升子序列 O(nlogn)解法 (java)

    最长递增子序列问题:在一列数中寻找一些数,这些数满足:任意两个数a[i]和a[j],若i 设dp[i]表示以i为结尾的最长递增子序列的长度,则状态转移方程为: dp[i] = max{dp[j]+1} ...

  3. c语言最长递增子序列nlogn,最长递增子序列

    问题定义: 给定一个长度为N的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱).例如:给定一个长度为6的数组A{5, 6, 7, 1, 2, 8},则其最长的单调递增子序列为{5,6, ...

  4. 最长递增子序列O(NlogN)算法

    转载出处:https://www.felix021.com/blog/read.php?1587 最长递增子序列,Longest Increasing Subsequence 下面我们简记为 LIS. ...

  5. c语言最长递增子序列nlogn,十月常见算法考题、最长递增子序列,Leetcode第300题最长上升子...

    十月常见算法考题.最长递增子序列,Leetcode第300题最长上升子 十月常见算法考题.最长递增子序列,Leetcode第300题最长上升子序列的变种,我没见过乔丹,今天詹姆斯就是我的神! @Aut ...

  6. 最长递增子序列的两种解法

    以LeetCode-300为例: O(n^2)解法: dp数组表示以i结尾的最长递增子序列的长度 class Solution { public:int lengthOfLIS(vector<i ...

  7. 最长递增子序列问题的求解

    一, 最长递增子序列问题的描述 设L=<a1,a2,-,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,-,akm>,其中k1<k2 ...

  8. 洛谷P2766-最长递增子序列问题

    chunlvxiong的博客 题目描述: 给定正整数序列x1,...,xn (1≤n≤500). 1.计算其最长递增子序列的长度s. 2.计算从给定的序列中最多可取出多少个长度为s的递增子序列. 3. ...

  9. 最长上升子序列(LIS) nlogn解法

    文章目录 经典DP解法O(n^2) dp+二分法(O(nlogn)) 最长上升子序列LIS:Longest increasing subsequence 题目链接:Leetcode300. 最长递增子 ...

  10. 动态规划算法-04最长递增子序列问题

    最长递增子序列问题 简述 经典的动态规划问题. 问题描述 给定一个序列,求解其中长度最长的递增子序列. 问题分析 这种可以向下查询答案的很容易想到动态规划的解法. 要求长度为i的序列Ai={a1,a2 ...

最新文章

  1. Qt5.9 OpenCV3.2.0测试例程(Win10)
  2. 调用模块,加入系统路径
  3. Angular 使用 Injector API 人工获取依赖注入的实例
  4. Linux文件和目录权限:chmod、更改所有者和所属组:chown,umask命令,隐藏权限:lsattr/chattr...
  5. 添加远程链接MySQL的权限
  6. 消息透露苹果新款MacBook Pro预计将在第三季度或第四季度发布
  7. 数据库-windows上安装mysql
  8. 笔记+R︱信用风险建模中神经网络激活函数与感知器简述
  9. mysql root dengru_Mysql学习Mysql中文汉字转拼音的实现(每个汉字转换全拼)
  10. uniapp 安装uView-ui教程
  11. 调用微信扫一扫接口---实现二维码扫描(微信浏览器)
  12. 如何将自己开发的网站部署到小鸟云服务器上?
  13. ictclas4j java_Paoding, Ik, Jeasy, Ictclas4j分词工具
  14. 【学习记录】QT5界面设计的踩坑记录
  15. 如何用一个IPad屏幕适配各尺寸的IPhone
  16. 相遇,是天意; 相守,是人意
  17. Sublime的实用汉化方法
  18. 通过matlab编程,对以下图像分别添加高斯噪声和椒盐噪声(参数自定),并使用理想低通滤波器、高斯低通滤波器和巴特沃斯低通滤波器进行去噪。
  19. 2020-7-3中兴IC开发设计师 专业面,
  20. Docker镜像的优化

热门文章

  1. 最小二乘法 几何意义
  2. python:epub文件批量转TXT
  3. 免费领取40本前端学习书籍【高清电子版】
  4. ps 打开失败 提示:暂存盘已满
  5. python windows开发环境_windows10下搭建Python3.6开发环境
  6. python接收163邮件以及下载附件(以163邮箱为例)
  7. BI报表工具有哪些?
  8. veu-cli 3.0使用教程
  9. 如何通俗易懂地理解递归
  10. 每一首歌曲的背后都有一段感人的故事……