首先引出一个例子

问题 :

  给你一个长度为 6 的数组 , 数组元素为 { 1 ,4,5,6,2,3,8 } , 则其最长单调递增子序列为 { 1 , 4 , 5 , 6 , 8 } , 并且长度为 5 。

分析 :

  题目所要找的递增子序列 , 想想有什么特点呢 ? 是不是会发现 所有的递增序列 ,前一个数一定小于后一个数 ,并且如果给所有从小到大的数标号 , 会得到一串递增的数 。

  既然是借助动态规划分析问题 , 那么当前的产生的结果 , 仅仅只与前一次状态有关 ,一直推的话 , 那么是不是就很自然地想到我最最简单的问题就是当数组中的元素只有一个的时候 , 并且我还要在开一个数组 , 记录所有元素的位置 。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std ; #define Min(a,b) a>b?b:a
#define Max(a,b) a>b?a:b int main ( ) {
int arr[7] = { 1 , 4 , 5 , 6 , 2 , 3 , 8 } ;
int pt[10] ; for ( int i = 0 ; i < 7 ; i++ )
pt[i] = 1 ;
for ( int i = 1 ; i < 7 ; i++ ) {
for ( int j = 0 ; j < i ; j++ ) {
if ( arr[i] > arr[j] && pt[j]+1 > pt[i] ) // 注意一定要是 pt[j]+1 > pt[i]
pt[i] = pt[j] + 1 ;
}
}
int maxn = 0 ;
for ( int i = 0 ; i < 7 ; i++ )
maxn = max ( maxn , pt[i] ) ; cout << maxn << endl ; return 0 ;
}

现在如果要输出这个递增的序列 , 要怎么做呢?

  

int maxn = 0 , t ;
for ( int i = 0 ; i < 7 ; i++ )
if ( maxn < dp[i] ) {
maxn = dp[i] ;
t = i ;
} for ( int i = 6 ; i >= 0 ; i-- ) {
if ( dp[i] == maxn ) {
cout << a[i] << '\t' ;
int f = a[i] , ff = dp[i] ;
for ( int j = i-1 ; j >= 0 ; j-- ) {
if ( f > a[j] && ff == dp[j]+1 ) {
cout << a[j] << '\t' ;
f = a[j] ;
ff = dp[j] ;
}
}
}
}

顺便给出 pt[ ] 数组中所存的数据

  

优化 :

  上述方法还是很好理解的 , 但是复杂度确实 n^2  , 现在有一种优化手段 , 可以将复杂度优化为 降为 n * log n ,这种方法的核心思想 ,  在二分下写 , 维护一个当前的最优的递增序列  , 找到恰好大于它的更新 。

举个小例子

  比如数组 a[ ] = { 1 , 3 , 2 , 4  } , 现将 a [ 1 ] 放入放入新数组 b [ ] 中 ,则 b[ 0 ] = 1 , 在 取出 a[ 1 ] = 3 , 将其放入 b 数组中 , 因为 3 恰好比 b[ 0 ] 大  , 所以 将 b[ 1 ] = 3  , 在拿出 a[ 2 ]  , 将 2 在数组 b 中二分 , 寻找位置 , 因为 2 恰好位于 1 和 3 之间 , 所以此时要用 2 去替换 3 的位置 ,即在 b 数组中得到一个新的有序的序列  , 但此序列并不是最长递增的子序列 ,它仅仅只是存储对应长度LIS 的最小末尾 。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std ; #define Min(a,b) a>b?b:a
#define Max(a,b) a>b?a:b int arr[7] = { 1 , 3 , 6 , 3 } ;
int dp[10] ; int fun ( int key , int l , int r ) {
int mid ;
if ( key >= dp[r] ) {
return r + 1 ;
}
while ( l <= r ) { // 二分查找,退出循环的前一次情况 , 一定是 l == r,如果 if 的判断里有等号 ,则 l 左移 ,否则 r 右移
mid = l + ( r - l ) / 2 ;
if ( dp[mid] <= key ) l = mid + 1 ;
else r = mid - 1 ;
} // printf ( "\n\n l = %d r = %d \n" , l , r ) ;
return l ;
} int main ( ) {
dp[0] = arr[0] ;
int len = 0 ;
for ( int i = 1 ; i < 4 ; i++ ) {
int f = fun ( arr[i] , 0 , len ) ;
dp[f] = arr[i] ;
if ( f > len ) len++ ;
} int cnt = 0 ;
for ( int i = 0 ; i < 4 ; i++ )
if ( dp[i] > 0 ) cnt++ ; cout << cnt << '\n' ;
return 0 ;
}

dp-最长递增子序列 (LIS)的更多相关文章

  1. 动态规划(DP),最长递增子序列(LIS)

    题目链接:http://poj.org/problem?id=2533 解题报告: 状态转移方程: dp[i]表示以a[i]为结尾的LIS长度 状态转移方程: dp[0]=1; dp[i]=max(d ...

  2. 最长回文子序列LCS,最长递增子序列LIS及相互联系

    最长公共子序列LCS Lintcode 77. 最长公共子序列 LCS问题是求两个字符串的最长公共子序列 \[ dp[i][j] = \left\{\begin{matrix} & max(d ...

  3. 2.16 最长递增子序列 LIS

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

  4. 一个数组求其最长递增子序列(LIS)

    一个数组求其最长递增子序列(LIS) 例如数组{3, 1, 4, 2, 3, 9, 4, 6}的LIS是{1, 2, 3, 4, 6},长度为5,假设数组长度为N,求数组的LIS的长度, 需要一个额外 ...

  5. 算法之动态规划(最长递增子序列——LIS)

    最长递增子序列是动态规划中最经典的问题之一,我们从讨论这个问题开始,循序渐进的了解动态规划的相关知识要点. 在一个已知的序列 {a1, a 2,...an}中,取出若干数组成新的序列{ai1, ai ...

  6. [DP]最长递增子序列

    #include <iostream> #include <limits.h> #include <vector> #include <algorithm&g ...

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

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

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

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

  9. 最长递增子序列 LIS 时间复杂度O(nlogn)的Java实现

    关于最长递增子序列时间复杂度O(n^2)的实现方法在博客http://blog.csdn.net/iniegang/article/details/47379873(最长递增子序列 Java实现)中已 ...

  10. HDU-1160-FatMouse's Speed(DP, 最长递增子序列)

    链接: https://vjudge.net/problem/HDU-1160 题意: FatMouse believes that the fatter a mouse is, the faster ...

随机推荐

  1. Springboot-webscoket with sockjs

    新建springboot maven工程,引入以下包 <dependency> <groupId>org.springframework.boot</groupId> ...

  2. MySQL之Field 'email' doesn't have a default value问题

    MySQL在出现这个Field xxx doesn't have a default value错误的原因是:我们设置了该字段为非空,但是我们没有设置默认值照成的. 比如我们创建一个表: CREATE ...

  3. Lavarel之环境配置 .env

    .env 文件位于项目根目录下,作为全局环境配置文件. 1. 配置参数 // 运行环境名称 APP_ENV=local // 调试模式,开发阶段启用,上线状态禁用. APP_DEBUG=true // ...

  4. java 类加载器的委托机制

    l 当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢? 1.首先当前线程的类加载器去加载线程中的第一个类. 2.如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B. 3 ...

  5. 原生PHP实现Mysql数据分页功能

    一. 思路整理 实现一个数据分页功能,需要有数据的总条数,每页展示的条数,和当前在第几页这三个参数 通过⌈总条数/每页展示的条数⌉可以得到总页数,比如某留言板有101条留言,每页展示10条,一那就需要 ...

  6. 微信小程序之在线答题(2)

    Tips:前端进阶的概念一直比较模糊,我们往往以掌握知识的多少来划分初级中级和高级,但这并不全面,谁都不能保证自己掌握的知识是最全最好的,尤其在前端工程师这个职业,每天都是日新月异. 所以,我认为要分 ...

  7. tensorflow在文本处理中的使用——skip-gram & CBOW原理总结

    摘自:http://www.cnblogs.com/pinard/p/7160330.html 先看下列三篇,再理解此篇会更容易些(个人意见) skip-gram,CBOW,Word2Vec 词向量基 ...

  8. 【30.01%】【hdu 3397】Sequence operation

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submissio ...

  9. java.util.Date和jdk1.8新时间API比拼

    旧的时间和日期的API的缺陷 Java 的 java.util.Date 和 java.util.Calendar 类易用性差,不支持时区,而且都不是线程安全的. Date如果不格式化,打印出的日期可 ...

  10. Tomcat 类加载器打破双亲委派模型

    我们分为4个部分来探讨: 1. 什么是类加载机制? 2. 什么是双亲委任模型? 3. 如何破坏双亲委任模型? 4. Tomcat 的类加载器是怎么设计的? 我想,在研究tomcat 类加载之前,我们复 ...