首先引出一个例子

问题 :

  给你一个长度为 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. PHP开源框架Laravel的安装与配置

    编将带领大家一步步在Windows 7平台下搭建该框架: 工具/原料   windows 7 Composer Laravel最新框架 方法/步骤   1 安装composer.安装之前要确保目录:w ...

  2. 【t085】Sramoc问题

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] Sramoc(K,M)表示用数字0,1,2,...,K-1组成的自然数中能被M整除的最小数.给定K,M ...

  3. 使用vuex来管理数据

    最近一直工作比较忙,博客已经鸽了好久了,趁着今天是周末,写点东西吧 使用vuex来管理数据 最近一直在用vue做项目,但是却从来没真正去用过vuex,因为一直感觉很复杂,其实真正去研究一下啊,就会发现 ...

  4. dotnet 通过 WMI 获取系统安装软件

    本文告诉大家如何通过 WMI 获取系统安装的软件,这个方法不能获取全部的软件 通过 Win32_Product 可以获取系统安装的软件 var mc = "Win32_Product&quo ...

  5. eclipse中maven报错--Dmaven.multiModuleProjectDirectory system propery is not set. Check $M2_HOME environment variable and mvn script match.

    -Dmaven.multiModuleProjectDirectory system propery is not set. Check $M2_HOME environment variable a ...

  6. D3.js力导向图中新增节点及新增关系连线示例

    大家在使用D3.js中的力导向图时,基本都会遇到动态增加节点及连线的需求,这里记录一下我的实现方式. 话不多说,先放代码: <!DOCTYPE html> <html lang=&q ...

  7. springboot-aop日志打印

    package com.cinc.ecmp.client; import com.cinc.ecmp.enums.BackResultEnum; import com.cinc.ecmp.except ...

  8. C# 已知点和向量,求距离的点

    已知一个点 P 和向量 v ,求在这个点P按照向量 v 运行距离 d 的点 B . 已经知道了一个点 P 和他运动方向 v ,就可以通过这个求出距离点 P 为 d 的点 B. 首先把 v 规范化,规范 ...

  9. C#调用smtp邮件发送几个大坑

    1.网易.新浪邮箱新增了一个叫“授权码”的东西,开通smtp服务时,必须开启授权码,并且邮件发送代码中也需要加上授权码,如下代码: //指定邮箱账号和密码,需要注意的是,这个密码是你在邮箱设置里开启服 ...

  10. .Net Core解除文件上传大小限制

    一共要修改两处地方: \Startup.cs public void ConfigureServices(IServiceCollection services) { services.AddMvc( ...