LIS(Longest Increasing Subsequence)是一类典型的动态规划类问题,简化描述如下:

给定$N(n) = \{1,2...,n\}$的一个排列$P(n)$,求$P(n)$中最长上升子列的长度。

譬如令$n = 6$, $N(6) = \{1,2,3,4,5,6\}$,$P(n) = \{1,4,2,5,3,6\}$。

容易发现$LIS(P(n)) = \{1,2,3,6\} or \{1,4,5,6\}...$。

起初我们拿到问题的思路是这样的,我们试着先分析序列的前缀,考虑P(n)中前k项的LIS,即试图分析$LIS(P(k)), k <= n$,

记$P(n) = A$,考虑由$k->k+1$的递推,若$A(k+1) > A(k)$,我们显然有$LIS(P(k+1)) = 1 + LIS(P(k))$,但若$A(k+1) < A(k)$,

则有$A(k+1) = max{LIS(P(i))} + 1, (A(i) < A(k+1), i <= k)$,那么这样做的复杂度为$O(n)$,求$LIS(P(n))$的复杂度为$O(n^2)$。

能不能更快点呢,我们的计算是否有冗余呢?我们知道答案是肯定的。

比如我们在检查到A(k)项时希望知道所有已经检查过的项对应的LIS的最大值,这样我们取其值加一即可得$LIS(P(k))$。

我们试图维护这样的一个数据结构,以线段树为例,我们构建一颗覆盖区间$[1...n]$的线段树,所有叶子结点value值初始化为$-∞$。

假设在检查$A(k)$之间线段树上储存了之前所有已访问过的项计算LIS时的信息,那么在计算$LIS(P(k))$时,我们取$[1,...A(k) - 1]$区间的最大值,

那么有区间内未访问项的值仍未$-∞$,已访问项的最大值即为所取,我们将其加一得到$LIS(P(k))$,为了维护该结构,将叶子结点A(k)对应的值更新为$LIS(P(k))$,

每次操作的复杂度为$O(logn)$,总复杂度为$O(nlogn)$。

虽然复杂度降低了,但是我们觉得使用线段树解决这个问题可能并非必要,能不能用更简单的方法实现同样复杂度的算法?

或者说,我们之前$O(n^2)$算法其使用的数据结构有何改进之处,如何重新组织信息才能使其更有利于解题?

------------------------------------------------------------

注意到我们之前关心的是项所对应位置,然后根据其位置查找其LIS并更新答案,实际上我们关心的只是满足$A(i) < A(k)$对应的最大LIS值,然而我们需要认识到

的是$A(k)$是在不断变化的,然而右边LIS的值则是便于处理的,并且具有单调可更新性。这就是问题解决的入口。

考虑固定LIS值,储存LIS值等于它的最小项,那么在检查A(k)时,只需用二分查找便可求得可以最为当前项前导项对应的LIS最大值,其后再对该序列用当前LIS更新即可。

时间复杂度为$O(nlogn)$,空间复杂度为$O(n)$。

高效的算法需要对原始数据加以更充分的利用,使之更容易呈现出实际问题的本质,使子问题更加主动地成为整个个问题解决的关键有效部分。

算法心得1:由$nlogn$复杂度的LIS算法引起的思考的更多相关文章

  1. 4. 文本相似度计算-CNN-DSSM算法

    1. 文本相似度计算-文本向量化 2. 文本相似度计算-距离的度量 3. 文本相似度计算-DSSM算法 4. 文本相似度计算-CNN-DSSM算法 1. 前言 之前介绍了DSSM算法,它主要是用了DN ...

  2. 3. 文本相似度计算-DSSM算法

    1. 文本相似度计算-文本向量化 2. 文本相似度计算-距离的度量 3. 文本相似度计算-DSSM算法 4. 文本相似度计算-CNN-DSSM算法 1. 前言 最近在学习文本相似度的计算,前面两篇文章 ...

  3. 《数据结构与算法之美》 <01>复杂度分析(上):如何分析、统计算法的执行效率和资源消耗?

    我们都知道,数据结构和算法本身解决的是“快”和“省”的问题,即如何让代码运行得更快,如何让代码更省存储空间.所以,执行效率是算法一个非常重要的考量指标. 那如何来衡量你编写的算法代码的执行效率呢?这里 ...

  4. 编程之法:面试和算法心得(寻找最小的k个数)

    内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java 题目描述 输入n个整数,输出其中最小的k个. 分析与解法 解法一 要求一个序列中最小的k个数,按照惯有的思维方式,则是先对这个 ...

  5. 编程之法:面试和算法心得(字符串包含java实现)

    内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java 题目描述 给定两个分别由字母组成的字符串A和字符串B,字符串B的长度比字符串A短.请问,如何最快地判断字符串B中所有字母是否都 ...

  6. 编程之法:面试和算法心得(旋转字符串java实现)

    内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java 题目描述 给定一个字符串,要求把字符串前面的若干个字符移动到字符串的尾部,如把字符串“abcdef”前面的2个字符'a'和'b ...

  7. 挑子学习笔记:两步聚类算法(TwoStep Cluster Algorithm)——改进的BIRCH算法

    转载请标明出处:http://www.cnblogs.com/tiaozistudy/p/twostep_cluster_algorithm.html 两步聚类算法是在SPSS Modeler中使用的 ...

  8. 算法与设计模式系列1之Python实现常见算法

    preface 常见的算法包括: 递归算法 二分法查找算法 冒泡算法 插入排序 快速排序 二叉树排序 下面就开始挨个挨个的说说原理,然后用Python去实现: 递归算法 一个函数(或者程序)直接或者间 ...

  9. Java常用排序算法+程序员必须掌握的8大排序算法

    概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 我们这里说说八大排序就是内部排序. 当n较大, ...

随机推荐

  1. 随机删除数据库N条记录

    delete from  table where newsID in(select top 50 newsID from  table order by newid())

  2. Leetcode: Range Sum Query - Mutable && Summary: Segment Tree

    Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive ...

  3. 转:python webdriver API 之鼠标事件

    前面例子中我们已经学习到可以用 click()来模拟鼠标的单击操作,而我们在实际的 web 产品测试中 发现,有关鼠标的操作,不单单只有单击,有时候还要和到右击,双击,拖动等操作,这些操作包含在Act ...

  4. sdutoj 2603 Rescue The Princess

    http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2603 Rescue The Princess ...

  5. Java里的File I/O

    Java的输入流主要由:InputStream和Reader作为基类,把持久化数据读入内存.输出流由OutputStream和Write类作为父类. 其中读如内存的时候,不可能一下去全读进去,需要一个 ...

  6. 什么是XML

    什么是 XML? XML 指可扩展标记语言(EXtensible Markup Language) XML 是一种标记语言,很类似 HTML XML 的设计宗旨是传输数据,而非显示数据 XML 标签没 ...

  7. react 绑定事件

    1.显示隐藏 2.输入框输入内容,立即显示出来 代码如下: 注意:版本 React v15.0.1 ReactDOM v15.0.1 browser.min.js是编译文件,将代码解析为浏览器识别的j ...

  8. zw版【转发·台湾nvp系列Delphi例程】HALCON Component Histogram

    zw版[转发·台湾nvp系列Delphi例程]HALCON Component Histogram unit Unit1;interfaceuses Windows, Messages, SysUti ...

  9. Auto push git tag

    CALL "C:\Program Files\TortoiseGit\bin\pageant.exe" "d:\CKey.ppk" set GIT_SSH=C: ...

  10. redis面试题总结

    1. 使用redis有哪些好处? (1) 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1) (2) 支持丰富数据类型,支持string,li ...