最早见到这道题目是在poj中,具体的题目忘记了,但是所要求的算法是一致的。

当时在学习LCS,因此想了一种和LCS比较相似的解法:

对原数组使用快速排序,然后使用LCS的思想求最大公共字串。 这种解法比较容易理解,但是所需要的空间为:O(2N) = O(N);时间为O(N^2+N*lgN) = O(N^2),显然这不是一种最优的解法。但是当时还真没有想到更好的解法……

最近看到编程之美上面的题目,然后豁然开朗。

书中提供了两个解法:

1. 根据无后效性的定义,可以使用DP来进行求解。根据递推公式:LIS[i+1] = max{LIS[i+1],LIS[k]+1} (当Data[i+1] > Data[k], 并且k∈[0,i]

在得出了上述的通项公式之后,可以简单的写代码求解了。但是这里需要注意的就是在for循环当中不停地更新当前的最大值,方便函数最后的结果返回。这个解法是传统的DP,因此时间复杂度为O(N^2),空间复杂度为O(N),但是在渐进意义上优于我的解法。

2. 当考虑前i个元素对i+1个元素的影响时,可以这样简答的理解:当子序列的最大元素比当前元素小时,就可以把当前元素添加到这个序列后面,构成一个新的LIS。

因此需要找到前i个元素的一个LIS,而且这个LIS的最大元素比Array[i+1]小,且长度尽可能的长。

为了加速算法的实现,构建一个长度为N的数组来维护长度为i的LIS的最大值。

因此该算法的时间复杂度是O(N^2),空间复杂度是O(2N) = O(N)。

上述算法的实现如下:

(二分查找的改进没有实现……)

//数组中最长递增子序列 #include <iostream> using namespace std; template<class T> inline T MaxInTwoElement(const T&a, const T &b) {return a>b?a:b; } int Slove1(const int *, int);//使用DP寻找,O(N^2), DP[i] = Max{DP[j]+1,DP[i]}(DP[i]>DP[j]) int Slove2(const int *, int);//使用另外的数组保存长度为n的LIS最大元素的最小值 int Slove3(const int *, int); int Dp[20]; void Initialize() {memset(Dp,0,sizeof(Dp));Dp[0] = 1; } int main() {int (*p[3])(const int*, int) = {&Slove1,&Slove2,&Slove3};int Data[] = {1,-1,2,-3,4,-5,6,-7};for (int i = 0;i<3;++i){cout<<p[i](Data,sizeof(Data)/sizeof(int))<<endl;}return 0; } int Slove1(const int *Data, int length) {Initialize();int Max = 1;for (int i = 1; i<length; ++i){for (int j = 0; j<i; ++j){if (Data[i] > Data[j]){Dp[i] = MaxInTwoElement(Dp[j] + 1,Dp[i]);}}Max = Max>Dp[i]?Max:Dp[i];}return Max; } int Slove2(const int *Data, int length) {int *MaxEle = new int[length +1];MaxEle[0] = -INT_MAX;MaxEle[1] = Data[0];//initializefor (int i =0; i<length; ++i)Dp[i] = 1;int maxLength = 1;for (int i=1; i<length; ++i)//traversing the array{int j;for (j=maxLength; j>-1; --j)//find the Max element int the LIS{if (Data[i] > MaxEle[j])//j is the length of sequence, too{//means it can be added to the sequenceDp[i] = j+1;break;}}//now j = 0 or the index which firstly satisfied Data[i] > MaxEle[j] if (Dp[i] > maxLength){//update the length and the element in MaxEle according to the lengthmaxLength = Dp[i];MaxEle[Dp[i]] = Data[i];}else if(Data[i] > MaxEle[j] && Data[i] < MaxEle[j+1]){//当前的值并不比最大长度大,则更新MaxEle[j+1] = Data[i];}}return maxLength; } int Slove3(const int *Data, int length) {int *MaxEle = new int[length +1];MaxEle[0] = -INT_MAX;MaxEle[1] = Data[0];//initializefor (int i =0; i<length; ++i)Dp[i] = 1;int maxLength = 1;for (int i=1; i<length; ++i)//traversing the array{int j; // int bg = 0; // int end = maxLength;//here, cuz the MaxEle is ordered( can be proved), //we can use binary search // while (true) // { // j = (bg +end)/2; // if (Data[i] > MaxEle[j]) // { // Dp[i] = j+1; // break; // } // else // { // end = j; // } // }for (j=maxLength; j>0; --j)//find the Max element int the LIS{if (Data[i] > MaxEle[j])//j is the length of sequence, too{//means it can be added to the sequenceDp[i] = j+1;break;}}//now j = 0 or the index which firstly satisfied Data[i] > MaxEle[j] if (Dp[i] > maxLength){//update the length and the element in MaxEle according to the lengthmaxLength = Dp[i];MaxEle[Dp[i]] = Data[i];}else if(Data[i] > MaxEle[j] && Data[i] < MaxEle[j+1]){//当前的值并不比最大长度大,则更新MaxEle[j+1] = Data[i];}}return maxLength; }

编程之美--数组中的最长递增子序列(LIS longest increasement sequence)相关推荐

  1. 编程之美 求数组中的最长递增子序列

    如题,例如:存在数组 1,-1,2,-3,4,-5,6,-7 ,则最长的递增子序列是:1,2,4,6. 法一: 蛮力法 int Lis(int* arr,int n) {int iCount=0;// ...

  2. 求数组中的最长递增子序列

    RT: 代码如下: 1 int lisq(int * a,int N) 2 { int e1=a[0],e2=a[0]; 3 int L1=1,L2=1; 4 int i; 5 6 for(i=1;i ...

  3. 耐心排序之最长递增子序列(LIS)

    目录 一.问题引入 1.最长递增子序列(LIS) 2.问题分析 3.代码实现 4.问题思考 二.耐心排序 1.基本介绍 2.操作步骤 3.代码实现 三.俄罗斯套娃信封问题 1.题目描述 2.问题分析 ...

  4. vue3源码中的最长递增子序列

    求解最长递增子序列是一道经典的算法题, 多数解法是使用动态规划的思想,算法的时间复杂度是O(); 而Vue.js内部使用的是维基百科提供的一套"贪心+二分查找"的算法; 贪心算法的 ...

  5. python最大连续递增子列_最长递增子序列(LIS)解法详述

    求数组中最长递增子序列(Longest Increasing Subsequence, LIS) LIS问题是算法中的经典题目,传统的解法是使用动态规划,时间复杂度是O(n^2):改进的方法时间复杂度 ...

  6. 最长递增子序列LIS再谈

    DP模型: d(i) 以第 i 个元素结尾的最长递增子序列的长度. 那么就有 d(i) = max(d(j)) + 1;(j<i&&a[j]<a[i]),答案 max(d( ...

  7. 编程之美-求数组中最长递增子序列(LIS)方法整理

    [试题描述] 方法一:时间复杂度O(n^2) 方法二:时间复杂度O(n^2) 方法三: 修改方法二中的穷举搜索部分为如下: 如果把上述查询部分利用二分搜索进行加速,可以得到时间复杂度为O(nlogn) ...

  8. 数组中的最长连续子序列

    给定无序数组arr,返回其中最长的连续序列的长度(要求值连续,位置可以不连续,例如 3,4,5,6为连续的自然数) 示例1 输入 [100,4,200,1,3,2] 返回值 4 示例2 输入 [1,1 ...

  9. 动态规划 - 最长递增子序列LIS

    问题:一个序列有N个数:A[1],A[2],-,A[N],求出最长非降子序列的长度 样例输入:3 1 2 6 5 4 思路: 首先把问题简单化.可以先求A[1],...A[i]的最长非降子序列,令dp ...

  10. 程序员面试100题之十二:求数组中最长递增子序列

    写一个时间复杂度尽可能低的程序,求一个一维数组(N个元素)中最长递增子序列的长度. 例如:在序列1,-1,2,-3,4,-5,6,-7中,其最长递增子序列为1,2,4,6. 分析与解法 根据题目要求, ...

最新文章

  1. C#调用COM组件遇到的问题及解决办法
  2. hardnet68尝试
  3. (一)Linux基本知识
  4. C++学习笔记7[指针]
  5. day4 Python的selenium库
  6. 解决vscode之前好好的能连接上linux服务器,后来报错,窗口出现故障
  7. 步步为营-75-Cookie简介
  8. VMware虚拟机CentOS7 - VMnet8网络配置及常见问题解决
  9. bzoj 1040: [ZJOI2008]骑士
  10. 复合索引失效的几种情况
  11. NetSuite 在中国 - 一个全程信息化管理平台
  12. 黑客攻防技术宝典:浏览器实战篇 -- 上篇(笔记)
  13. python 取整求余函数
  14. Android微信登录
  15. Python3---有关日期的处理---最近自然周最近自然月最近一周最近一月---dateutil模块
  16. AR体感大屏互动系统解决方案
  17. ISO/IEC 9126软件质量标准
  18. 手写一个迷你版的 Tomcat 喵
  19. 云服务器、VPS、虚拟主机三者之间的区别?
  20. JAVA综合性实验——猜姓氏游戏

热门文章

  1. 搜狗输入法双拼 linux,Ubuntu搜狗输入法设置双拼
  2. java图片黑白_java – 将图像转换为黑白图像
  3. 俄勒冈之旅_我在俄勒冈州SAO软件协会上通过A hrefhttpdbsaoorgcalendarofeventseventdescription进行介绍...
  4. python小组项目总结报告_项目总结报告多篇汇总
  5. 3Dmax2014安装问题
  6. 《Linux命令行与shell脚本编程大全(第3版)》读书笔记
  7. JavaScript(基础知识)
  8. shader编程-三维场景下SDF建模,对模型进行扭曲、弯曲、裁剪、掏空操作(WebGL-Shader开发基础12)
  9. 广东省高清卫星影像数据包下载
  10. R 单独窗口显示绘图(plots)