dp-最长递增子序列 (LIS)
首先引出一个例子
问题 :
给你一个长度为 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)的更多相关文章
- 动态规划(DP),最长递增子序列(LIS)
题目链接:http://poj.org/problem?id=2533 解题报告: 状态转移方程: dp[i]表示以a[i]为结尾的LIS长度 状态转移方程: dp[0]=1; dp[i]=max(d ...
- 最长回文子序列LCS,最长递增子序列LIS及相互联系
最长公共子序列LCS Lintcode 77. 最长公共子序列 LCS问题是求两个字符串的最长公共子序列 \[ dp[i][j] = \left\{\begin{matrix} & max(d ...
- 2.16 最长递增子序列 LIS
[本文链接] http://www.cnblogs.com/hellogiser/p/dp-of-LIS.html [分析] 思路一:设序列为A,对序列进行排序后得到B,那么A的最长递增子序列LIS就 ...
- 一个数组求其最长递增子序列(LIS)
一个数组求其最长递增子序列(LIS) 例如数组{3, 1, 4, 2, 3, 9, 4, 6}的LIS是{1, 2, 3, 4, 6},长度为5,假设数组长度为N,求数组的LIS的长度, 需要一个额外 ...
- 算法之动态规划(最长递增子序列——LIS)
最长递增子序列是动态规划中最经典的问题之一,我们从讨论这个问题开始,循序渐进的了解动态规划的相关知识要点. 在一个已知的序列 {a1, a 2,...an}中,取出若干数组成新的序列{ai1, ai ...
- [DP]最长递增子序列
#include <iostream> #include <limits.h> #include <vector> #include <algorithm&g ...
- 最长递增子序列LIS再谈
DP模型: d(i) 以第 i 个元素结尾的最长递增子序列的长度. 那么就有 d(i) = max(d(j)) + 1;(j<i&&a[j]<a[i]),答案 max(d( ...
- 算法面试题 之 最长递增子序列 LIS
找出最长递增序列 O(NlogN)(不一定连续!) 参考 http://www.felix021.com/blog/read.php?1587%E5%8F%AF%E6%98%AF%E8%BF%9E%E ...
- 最长递增子序列 LIS 时间复杂度O(nlogn)的Java实现
关于最长递增子序列时间复杂度O(n^2)的实现方法在博客http://blog.csdn.net/iniegang/article/details/47379873(最长递增子序列 Java实现)中已 ...
- HDU-1160-FatMouse's Speed(DP, 最长递增子序列)
链接: https://vjudge.net/problem/HDU-1160 题意: FatMouse believes that the fatter a mouse is, the faster ...
随机推荐
- js基础-原型
1.定义:我们创建的函数都有一个prototype(原型)属性,该属性是一个对象, 原型模式声明中多了两个属性(自动生成). 构造函数: function Box(nam ...
- P1073 奇数还是偶数
题目描述 给你 \(N(1 \le N \le 1000)\) 个数,你需要判断每个数是奇数还是偶数. 输入格式 输入的第一行包含一个整数 \(N(1 \le N \le 1000)\) . 接下来 ...
- Character.digit()的意义
最近在阅读Integet.parseInt()源码时,遇到了Character.digit()这个方法,以前没有遇到过,更没使用过,这里查了资料就记录一下. 官方说法是: java.lang.Char ...
- 2019-4-10-win10-uwp-自定义标记扩展
title author date CreateTime categories win10 uwp 自定义标记扩展 lindexi 2019-04-10 09:46:13 +0800 2019-04- ...
- jquery监听输入框只能输入数字
$('#mm').bind('input propertychange',function(){ var val= $(this).val(); if(val!=''&& isNaN( ...
- js 对象的深拷贝
function deepCopy(obj) { var result = Array.isArray(obj) ? [] : {}; for (var key in obj) { if (obj.h ...
- 遍历$.map和$.each
<body> <p style="color:red;"><b>Values: </b></p> <form> ...
- LuoguP3045牛券Cow Coupons
LuoguP3045 [USACO12FEB]牛券Cow Coupons 果然我贪心能力还是太差了 ZR讲过的原题我回来对做法没有一丁点印象 有时候有这样一种题目 每个数有两种不同的价值 你可以选择价 ...
- 【u034】追查坏奶牛
Time Limit: 1 second Memory Limit: 128 MB [问题描述] 你第一天接手三鹿牛奶公司就发生了一件倒霉的事情:公司不小心发送了一批有三聚氰胺的牛奶.很不幸,你发现这 ...
- 10款Web前端工具
10款让Web前端开发人员生活更轻松的实用工具.每个Web开发人员都有自己的工具箱,这样工作中碰到的每个问题都有一个好的解决方案供选择. 对于每一项工作,开发人员需要特定的辅助工具,所以如果下面这些工 ...