最长递增子序列(LIS)

问题描述:

求一个序列的最长递增子序列,这样的子序列是允许中间越过一些字符的,即留“空”。

例如:4 2 3 1 5 的最长递增子序列为 2 3 5,长度为 3 。

解法:

这里给出两种动态规划的做法,第二种是比较优化的 dp 。

① dp:dp[i] 表示以 i 结尾的最长递增子序列长度

第一个元素直接设置 LIS 长度为 1 即可。

处理第二个元素 2 的时候判断是否比前面的元素 4 大,没有的话那么以 2 为结尾的 LIS 就是 2,

即 LIS 长度为 1。

处理第三个元素 3 的时候需要跟前面的每个元素都进行比较,3 大于 2,则 LIS 的长度可能为 dp[1] + 1,

3 小于 4,则 LIS 的长度可能为 1,比较dp[1] + 1 和 1,取最大值,为 2 。

处理第四个元素 1,发现比前面的元素都小,那么以 1 为结尾的 LIS 只可能为 1,因此 LIS 的长度为 1。

处理最后一个元素 5,发现比前面的元素都大,那么以 5 结尾的 LIS 的长度可能为

dp[0] + 1,dp[1] + 1,dp[2] + 1,dp[3] + 1。

其中的最大值为 dp[2] + 1 = 3,因此 LIS 的长度为 3。

总结:

dp[i] 默认都为 1,因为以 i 结尾的 LIS 至少包含自己。

在 dp 表 0~i-1 中比对时,若 arr[i] > arr[j],

那么 dp[j] + 1 可能为 dp[i] 的最终值。

需要在所有的可能值中取最大值。

时间复杂度为 O(n2)。

② dp:dp[i] 表示长度为 i 的最长递增子序列(LIS)末尾的数

第一个元素直接加入 dp 表,dp[1] = 4,表示长度为 1 的 LIS 末尾的数当前为 4。

第二个元素为 2,因为 2 < 4,直接替换掉 4,dp[1] = 2 。

因为后面序列中的数字 > 2 的几率一定比 > 4 的几率高,有种贪心的感觉。

第三个元素为 3,由于 3 > dp[1] = 2,构成递增,dp[2] = 3,表示长度为 2 的 LIS 的末尾为 3 。

第四个元素为 1,由于 1 < dp[2] = 3,因此在前面一定有一个位置可以换成 1,

并且后面的递增性质不会被破坏。

第一个 > 1 的为 dp[1] = 2,因此将 dp[1] 置为 1。

最后一个元素为 5, 5 > dp[2] = 3,构成递归,故dp[3] = 5。

全部遍历完成,这个时候我们就可以发现 dp 数组的下标 3 就是我们要求的 LIS 长度。

参考代码:

// 这里的最长递增子序列是允许中间跨越其他子序列的
#include<iostream>
#include<algorithm>
using namespace std;int *arr;
int *dp;// 经典问题 dp[i]的意思为以i为结尾的最长子序列为多少
int getResult(int n)
{dp[0] = 1;for (int i = 1; i < n; i++){int cnt = 1;for (int j = i - 1; j >= 0; j--){if (arr[i] > arr[j]){  // 保证递增 cnt = max(cnt, dp[j] + 1);}}dp[i] = cnt;}int ans = 0;for (int i = 0; i < n; i++){ans = max(ans, dp[i]);}return ans;
}// 二分查找变体 找到第一个大于等于n的位置index
int BinarySearch(int *dp, int len, int n)
{int left = 1;int right = len;while (left < right){int mid = (left + right) / 2;if (dp[mid] >= n){right = mid;}else{left = mid+1;}}return right;
}// 优化的dp dp数组的最终下标为答案
int getResult1(int n)
{dp[1] = arr[0];int index = 1;for (int i = 1; i < n; i++){if (arr[i] > dp[index]){// 更新index dp[++index] = arr[i];}else{// 把dp数组中第一个大于等于n的数字替换为arr[i] int tempIndex = BinarySearch(dp, index, arr[i]);dp[tempIndex] = arr[i];}}return index;
} int main(){int n;while (cin >> n){arr = new int[n];dp = new int[n+1]; for (int i = 0; i < n; i++){cin >> arr[i];}int ans = getResult1(n);cout << ans << endl;delete[] arr;delete[] dp;}return 0;
} 

【END】感谢观看

最长递增子序列(LIS)相关推荐

  1. 耐心排序之最长递增子序列(LIS)

    目录 一.问题引入 1.最长递增子序列(LIS) 2.问题分析 3.代码实现 4.问题思考 二.耐心排序 1.基本介绍 2.操作步骤 3.代码实现 三.俄罗斯套娃信封问题 1.题目描述 2.问题分析 ...

  2. python最大连续递增子列_最长递增子序列(LIS)解法详述

    求数组中最长递增子序列(Longest Increasing Subsequence, LIS) LIS问题是算法中的经典题目,传统的解法是使用动态规划,时间复杂度是O(n^2):改进的方法时间复杂度 ...

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

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

  4. 动态规划 - 最长递增子序列LIS

    问题:一个序列有N个数:A[1],A[2],-,A[N],求出最长非降子序列的长度 样例输入:3 1 2 6 5 4 思路: 首先把问题简单化.可以先求A[1],...A[i]的最长非降子序列,令dp ...

  5. 编程之美-求数组中最长递增子序列(LIS)方法整理

    [试题描述] 方法一:时间复杂度O(n^2) 方法二:时间复杂度O(n^2) 方法三: 修改方法二中的穷举搜索部分为如下: 如果把上述查询部分利用二分搜索进行加速,可以得到时间复杂度为O(nlogn) ...

  6. 数组字符串那些经典算法:最大子序列和,最长递增子序列,最长公共子串,最长公共子序列,字符串编辑距离,最长不重复子串,最长回文子串 (转)...

    作者:寒小阳 时间:2013年9月. 出处:http://blog.csdn.net/han_xiaoyang/article/details/11969497. 声明:版权所有,转载请注明出处,谢谢 ...

  7. [51Nod 1218] 最长递增子序列 V2 (LIS)

    传送门 Description 数组A包含N个整数.设S为A的子序列且S中的元素是递增的,则S为A的递增子序列.如果S的长度是所有递增子序列中最长的,则称S为A的最长递增子序列(LIS).A的LIS可 ...

  8. LIS 最长递增子序列问题

    一,    最长递增子序列问题的描述 设L=<a1,a2,-,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,-,akm>,其中k1< ...

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

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

  10. 51Nod-1134 最长递增子序列【LIS】

    1134 最长递增子序列 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递增的) 例如 ...

最新文章

  1. QT textedit 滚动条自动往下滚动
  2. 【前端开发】HTML入门与实战
  3. 向EXECL文件中导入数据的同时插入图片
  4. do{...}while(0) 的意义和用法
  5. @staticmethod用法
  6. 快速实现一个Http回调组件
  7. 201403-1_相反数的个数
  8. 渗透测试攻击(二)——wireshark过滤数据包语法详解
  9. spring.net与OracleODP结合时发生的版本问题
  10. Aiseesoft iPhone Unlocker for Mac解锁密码?详细教程
  11. python: excel单元格读取写入
  12. C# OpenFileDialog 打开文件对话框 打开多文件对话框; 并获取其路径,文件名,扩展名/后缀名
  13. sqlServer 如何查看数据库日志文件的大小
  14. 微信小程序 时间插件 (可以选择日期+星期)
  15. 判断正方形和圆形相交
  16. 程序员要实现财富自由,“出海”这条路该怎么走?
  17. namecheap 从域名绑定到SSL配置
  18. 高考数学必考知识点高中数学重点知识归纳
  19. 开源生物特征识别库 OpenBR
  20. html新增和删除行,html5页面结构的变化以及增加和删除标签的总结

热门文章

  1. MFC实现多编辑框的文本字体改变
  2. Android ui 透明度设置
  3. 网络编程入门(JavaSE)
  4. h5邮件的邮箱 支持_html实现邮箱发送邮件_js发送邮件至指定邮箱功能
  5. (李兴华)【FANUC FOCAS1/2 Library 开发系列教程】-开发包概述
  6. unity学习笔记-番外(3d模型的动作设计以及导入-2018版)材质的替换以及动作穿模(自己的手穿模到自己的其他部位)
  7. CL4054DLTH7SOT23-5大电流500MA锂电充电芯片
  8. 乐理01(音程、定调、和弦的构成、拓展)
  9. xen EDD information not available
  10. 关于xss和csrf