LIS 最长递增子序列问题
一, 最长递增子序列问题的描述
设L=<a1,a2,…,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,…,akm>,其中k1<k2<…<km且aK1<ak2<…<akm。求最大的m值。
比如int* inp = {9,4,3,2,5,4,3,2}的最长递减子序列为{9,5,4,3,2};
二,解决:
1.用一个临时数组tmp保存这样一种状态:tmp[i]表示以i为终点的递增序列的长度;
比如inp = {3,2,5}那么tmp = {1, 1, 2},其中tmp[2]=2表示包含i=2位(inp[2]=5)的LIS的个数,即序列{3,5},个数为2;
2.假设已经知道了tmp[0]到tmp[n-1],那我们如何通过tmp[0]到tmp[n-1]的状态求得tmp[n]的状态?
比如inp = {3,2,5},已经求得tmp[0]=1,tmp[1]=1,怎么求tmp[2]?
如果i<2那,i就有可能在2为终点的LIS序列上,那以2为终点的递增序列的长度就至少是i的最长序列+1,那么就必须满足以下两个条件:
inp[i]<inp[n] tmp[i]+1>tmp[n]
比如i=0时,inp[0]=3<inp[n]=5且tmp[0]+1=2>tmp[2]=1(tmp[i]初值都为1);则赋值tmp[2] = tmp[0]+1=2;
继续比较i=1,此时inp[1]=2<inp[n]=5且tmp[1]+1=2不大于tmp[2]=2;
一直循环到n-1位为止!最后得到tmp = {1, 1, 2};
其中tmp的最大元素即为LIS的最大长度!
3.我们如何输出LIS的所有的值呢?
其实我们只需要知道LIS中,每个元素的前面一位元素的位置即可:
比如tmp = {1, 1, 2}的最大值是2,该LIS最后一位元素出现在i=2位,如果我们保存inp[2]=5在LIS中前面的那个元素,以此类推,我们就能找到LIS中所有元素;
比如{3,2,5}的LIS是{3,5}或{2,5},我们用另一个临时数组存储它前一位元素下标int arr = {-1,-1,0},表示以inp[2]=5结尾的LIS,其前一位元素的小标是0,即inp[0]=3,这样就找到了{3,2,5}的LIS是{3,5};
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <assert.h> //求最长递增子序列; //ret[i]存放包含第i位的LIS的元素个数; //path用于保存最长递增子序列路径;path[i]存放包含第i位的LIS的前一位元素的下标; int LIS(int* inp,int len,int* ret,int* path){assert(inp);if(len <= 0) return;int i = 0,max = 0,maxpoint = 0;for(;i<len;i++){ret[i] = 1;path[i] = -1;//初始值都-1,为了以后输出方便,初值0时和path[0]混淆;int j = 0;for(;j<i;j++){if(inp[i] > inp[j] && ret[j]+1 > ret[i]){ret[i] = ret[j] + 1;path[i] = j;}}printf("ret[i] ==%d\n",ret[i]);if(ret[i] > max){max = ret[i];maxpoint = i;//ret中最大的那个元素的下标; } }return maxpoint; }//输出数组 void printinp(int* inp,int len){int i = 0;for(;i<len;i++){printf("inp = %d\n",inp[i]);} }//输出LIS;LIS中-1表示:包含该位元素的LIS,其前面没有元素; void printpath(int* inp,int* path,int key){for(;key>=0;){printf("inp[%d]=%d\n",key ,inp[key]);if(key == 0) break;//path[0]处会死循环,必须跳出key = path[key];} }int main(){int inp[] = {2,9,4,6,8,7,1,3,5};int len = sizeof(inp)/sizeof(int);int ret[len];int path[len];int maxpoint = LIS(inp,len,ret,path);printpath(inp, path, maxpoint); }
输出结果:
ret[i] ==1 ret[i] ==2 ret[i] ==2 ret[i] ==3 ret[i] ==4 ret[i] ==4 ret[i] ==1 ret[i] ==2 ret[i] ==3 inp[4]=8 inp[3]=6 inp[2]=4 inp[0]=2
LIS结果是8 6 4 2,输出正确!
转载于:https://www.cnblogs.com/McQueen1987/p/4041707.html
LIS 最长递增子序列问题相关推荐
- 算法设计 - LCS 最长公共子序列最长公共子串 LIS 最长递增子序列
出处 http://segmentfault.com/blog/exploring/ 本章讲解: 1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度: 2. 与之类似但不 ...
- LIS 最长递增子序列
前言 LIS 即 longest increasing string,最长递增子序列,可以是不连续的.例如 2 3 5 2 3 4 5 的最长递增子序列为{2,3,4,5},长度为4. 两种方法可以求 ...
- 数组字符串那些经典算法:最大子序列和,最长递增子序列,最长公共子串,最长公共子序列,字符串编辑距离,最长不重复子串,最长回文子串 (转)...
作者:寒小阳 时间:2013年9月. 出处:http://blog.csdn.net/han_xiaoyang/article/details/11969497. 声明:版权所有,转载请注明出处,谢谢 ...
- [51Nod 1218] 最长递增子序列 V2 (LIS)
传送门 Description 数组A包含N个整数.设S为A的子序列且S中的元素是递增的,则S为A的递增子序列.如果S的长度是所有递增子序列中最长的,则称S为A的最长递增子序列(LIS).A的LIS可 ...
- 51Nod-1134 最长递增子序列【LIS】
1134 最长递增子序列 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递增的) 例如 ...
- 动态规划 —— 最长递增子序列(LIS)
LIS:Longest Increasing Subseq,最长递增子序列,是不要求该子序列在原始序列中间连续存放的. 为了降低对这一问题的理解难度,既然最长递增子序列不要求子序列位置连续,我们不妨先 ...
- 耐心排序之最长递增子序列(LIS)
目录 一.问题引入 1.最长递增子序列(LIS) 2.问题分析 3.代码实现 4.问题思考 二.耐心排序 1.基本介绍 2.操作步骤 3.代码实现 三.俄罗斯套娃信封问题 1.题目描述 2.问题分析 ...
- python最大连续递增子列_最长递增子序列(LIS)解法详述
求数组中最长递增子序列(Longest Increasing Subsequence, LIS) LIS问题是算法中的经典题目,传统的解法是使用动态规划,时间复杂度是O(n^2):改进的方法时间复杂度 ...
- CCNU ACM 2016夏季集训·最长递增子序列(LIS)
这几天dp写得难受-- 在讨论这个问题之前,首先明确:"子序列"是指从原序列中挑选出若干元素,按照原序列中的顺序组成新的序列(区别于"子串",即从原序列中挑选连 ...
最新文章
- 工信部 学习类app_工信部整治APP侵权行为,私自收集个人信息等8类问题被点名...
- 学习web前端开发要注意什么
- 简单读!tomcat源码(一)启动与监听
- 验证码实现(随机背景色及字体颜色,带扰乱线条)
- python基础教程:名称空间与作用域
- csdn的自动化评论
- 深度学习(二十三)——Fast Image Processing, SVDF, LCNN, LSTM进阶
- 提升开发效率的十个工具
- 哥廷根,世界数学家的摇篮和圣地
- docker部署web项目_IntelliJ IDEA 部署 Web 项目
- python知识总结os**
- 开元弧焊机器人编程_【数据】2019年中国焊接机器人市场发展现状与趋势分析...
- HFSS阵列天线仿真
- CameraLink简介
- 王道中数据结构的排序算法
- Python文件操作错误:OSError: [Errno 22] Invalid argument(关于Windows下文件名中的敏感字符)
- 测试之smart原则
- 机器学习 Cohen s Kappa,Quadratic Weighted Kappa 详解
- 2021年秋招面试真题以及面试技巧分享
- linux C-kermit 安装使用