首先引出一个例子

问题 :

  给你一个长度为 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. java UDP传输

    ①:只要是网络传输,必须有socket . ②:数据一定要封装到数据包中,数据包中包括目的地址.端口.数据等信息. 直接操作udp不可能,对于java语言应该将udp封装成对象,易于我们的使用,这个对 ...

  2. Vue仿网易云PC端的网页

    贴个网址:https://github.com/wangjie3186594/-PC- 声明一下:这个网页没做完!没做完!没做完!      本人新人一枚,按照的是我当前的学习进度做的项目,很多效果未 ...

  3. HDU - 4587 TWO NODES (图的割点)

    Suppose that G is an undirected graph, and the value of stab is defined as follows: Among the expres ...

  4. mysql find_in_set 与 in 的用法与区别,mysql范围搜索,mysql范围查询

    mysql find_in_set 与 in 的用法与区别 1.find_in_set 用于模糊查询,并且数据库中的值是用英文逗号分隔的: 例如: (1).去字段中查询 select find_in_ ...

  5. A non well formed numeric value encountered

    在从数据库获取时间戳数据的时候返回的结果是varchar类型 然后在用date("Y-m-d H:i:s", 时间戳)的时候会报错A non well formed numeric ...

  6. 微信 HTML5 VIDEO 视频播放解决方案

    原文链接:https://www.jianshu.com/p/e4573acf6564 webkit-playsinline && playsinline="true&quo ...

  7. 38.CSS

    转载:https://www.cnblogs.com/yuanchenqi/articles/5977825.html css概述 CSS是Cascading Style Sheets的简称,中文称为 ...

  8. 力扣90——子集 II

    原题 给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: [1,2,2] 输出: [ [2], [1], [1,2,2], ...

  9. Rxjava2 介绍与详解实例

    目录 前言 RX介绍 Rx模式 Rx使用依赖: Rxjava的入门基础 1. Observable 2. Flowable 3. Single 4. Completable 5. Maybe 6. S ...

  10. saltstack的配置使用

    介绍 认证管理,使其可以用于编配, 远程执行, 配置管理等等.部署轻松,在几分钟内可运行起来,扩展性好,很容易管理上万台服务器,速度够快,服务器之间秒级通讯. 号称世界上最快的消息队列ZeroMQ使得 ...