一,    最长递增子序列问题的描述

设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 <= ) return;
int i = ,max = ,maxpoint = ;
for(;i<len;i++){
ret[i] = ;
path[i] = -;//初始值都-1,为了以后输出方便,初值0时和path[0]混淆;
int j = ;
for(;j<i;j++){
if(inp[i] > inp[j] && ret[j]+ > ret[i]){
ret[i] = ret[j] + ;
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 = ;
for(;i<len;i++){
printf("inp = %d\n",inp[i]);
}
} //输出LIS;LIS中-1表示:包含该位元素的LIS,其前面没有元素;
void printpath(int* inp,int* path,int key){
for(;key>=;){
printf("inp[%d]=%d\n",key ,inp[key]);
if(key == ) break;//path[0]处会死循环,必须跳出
key = path[key];
}
} int main(){
int inp[] = {,,,,,,,,};
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] ==
ret[i] ==
ret[i] ==
ret[i] ==
ret[i] ==
ret[i] ==
ret[i] ==
ret[i] ==
ret[i] ==
inp[]=
inp[]=
inp[]=
inp[]=

LIS结果是8 6 4 2,输出正确!

LIS 最长递增子序列问题的更多相关文章

  1. 算法设计 - LCS 最长公共子序列&&最长公共子串 &&LIS 最长递增子序列

    出处 http://segmentfault.com/blog/exploring/ 本章讲解:1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度:2. 与之类似但不同的 ...

  2. LIS 最长递增子序列

    一.最长公共子序列 经典的动态规划问题,大概的陈述如下: 给定两个序列a1,a2,a3,a4,a5,a6......和b1,b2,b3,b4,b5,b6.......,要求这样的序列使得c同时是这两个 ...

  3. 300. Longest Increasing Subsequence(LIS最长递增子序列 动态规划)

    Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...

  4. 最长递增子序列(LIS)

    最长递增子序列(Longest Increasing Subsequence) ,我们简记为 LIS. 题:求一个一维数组arr[i]中的最长递增子序列的长度,如在序列1,-1,2,-3,4,-5,6 ...

  5. 最长公共子序列(LCS)和最长递增子序列(LIS)的求解

    一.最长公共子序列 经典的动态规划问题,大概的陈述如下: 给定两个序列a1,a2,a3,a4,a5,a6......和b1,b2,b3,b4,b5,b6.......,要求这样的序列使得c同时是这两个 ...

  6. 2.16 最长递增子序列 LIS

    [本文链接] http://www.cnblogs.com/hellogiser/p/dp-of-LIS.html [分析] 思路一:设序列为A,对序列进行排序后得到B,那么A的最长递增子序列LIS就 ...

  7. 算法面试题 之 最长递增子序列 LIS

    找出最长递增序列 O(NlogN)(不一定连续!) 参考 http://www.felix021.com/blog/read.php?1587%E5%8F%AF%E6%98%AF%E8%BF%9E%E ...

  8. 最长递增子序列(lis)最长公共子序列(lcs) 最长公共上升子序列(lics)

    lis: 复杂度nlgn #include<iostream> #include<cstdio> using namespace std; ],lis[],res=; int ...

  9. 最长递增子序列(LIS)(转)

    最长递增子序列(LIS)   本博文转自作者:Yx.Ac   文章来源:勇幸|Thinking (http://www.ahathinking.com)   --- 最长递增子序列又叫做最长上升子序列 ...

随机推荐

  1. css3简单几步画一个乾坤图

    原文:[原创]css3简单几步画一个乾坤图 效果如上,鼠标移上去会有动画. 代码如下非常简单: <html> <head> <style> .outer{heigh ...

  2. MVC自定义过滤器,自定义Area过滤器,自定义Controller,Action甚至是ViewData过滤器

    实现MVC自定义过滤器,自定义Area过滤器,自定义Controller,Action甚至是ViewData过滤器 MVC开发中几种以AOP方式实现的Filters是非常好用的,默认情况下,我们通过A ...

  3. 1.cocos2dx它Menu(CCMenuItemFont,CCMenuItemImage,CCMenuItemLabel,CCMenuItemSprite,CCMenuItemToggle)

     CCMenu 基本结构 CCMenu继承自CCLayer,本质是一个容器.须要被addChild到父类中去. CCMenuItem是菜单项,它有例如以下子类: CCMenuItemFont;CC ...

  4. 关于Java中List对象的分页思想,按10个或者n个数对list进行分组

    try { List<String> timelist = DateUtils.getDateListBySETime("2015-08-01", "2015 ...

  5. JavaScript/js把秒或者毫秒换算成xx-xx-xx 时-分-秒的形式

    function MillisecondToDate(msd) { // var time = parseFloat(msd) / 1000; var time=msd; if (null != ti ...

  6. javascript5

    调用对象call object: 声明上下文对象declarative environment record; 作用域链scopechain: 变量解析:variable resolution: 引用 ...

  7. PHP 1:在Windows上安装和配置PHP,Apache和My SQL

    原文:PHP 1:在Windows上安装和配置PHP,Apache和My SQL 如果你Google一把类似的主题,你会发现相关的文章可以塞满你的硬盘.在这里之所以把它再次拿出来,目的是想记录我作为一 ...

  8. OCP-1Z0-051-题目解析-第9题

    9. Which statement is true regarding the INTERSECT operator? A. It ignores NULL values. B. Reversing ...

  9. android App Widgets

    http://developer.android.com/guide/practices/ui_guidelines/widget_design.html#design http://develope ...

  10. DDD分层架构之我见

    DDD分层架构之我见 前面介绍了应用程序框架的一个重要组成部分——公共操作类,并提供了一个数据类型转换公共操作类作为示例进行演示.下面准备介绍应用程序框架的另一个重要组成部分,即体系架构支持.你不一定 ...