动态规划算法-04最长递增子序列问题
最长递增子序列问题
简述
- 经典的动态规划问题。
问题描述
- 给定一个序列,求解其中长度最长的递增子序列。
问题分析
- 这种可以向下查询答案的很容易想到动态规划的解法。
- 要求长度为i的序列Ai={a1,a2,a3,ai}的最长递增子序列,需要先求出序列Ai-1{a1,a2,a3,ai-1}中各元素(a1,a1,ai-1)作为最大元素的最长递增子序列,然后将这i-1个递增序列与ai进行比较。如果某个长度为m的序列的末尾元素aj(j<i)比ai小,则将元素ai加入这个递增子序列,得到一个长度为m+1的新序列,否则其长度不变,将处理后的i-1个序列的长度进行比较,最长的就是要求的最长递增子序列。
- 举个例子
- 对于序列A{3,1,4,5,9,2,6,5,0},当处理到第7个元素“6”时,i-1个序列为。
- 3
- 1
- 3,4
- 3,4,5
- 3,4,5,9
- 1,2
- 经过上述处理后,序列变为如下。有两个最长的。可见,以“6”为结尾的最长递增子序列为{3,4,5,6}。
- 3,6
- 1,6
- 3,4,6
- 3,4,5,6
- 3,4,5,9
- 1,2,6
- 同样,处理到第8个元素“5”的时候,原始序列处理后变为如下。
- 3,5
- 1,5
- 3,4,5
- 3,4,5
- 3,4,5,9
- 1,2,5
- 可见,以第8个元素“5”为结尾的最长递增子序列为{3,4,5}。
- 最后一个0,无法在后面添加,因此,这个题目的答案为{3,4,5,9}。序列A的最长递增子序列长度为4.
- 注意:求解到的最长递增子序列可能不止一个。
- 对于序列A{3,1,4,5,9,2,6,5,0},当处理到第7个元素“6”时,i-1个序列为。
- 设f(i)表示序列中以ai为末尾元素的最长递增子序列的长度,则在求以ai为末尾元素的最长递增子序列是,找到所有序号在i前面且小于ai的元素aj,即j<i且aj<ai。
- 如果这样的元素存在,那么对所有的aj,都有一个以aj为末尾元素的最长递增子序列的长度f(j)。把其中最大的f(j)找出来,f(i)就等于这个最大的f(j)+1。也就是说,以ai为末尾元素的最长递增子序列,等于在使f(j)最大的那个aj为末尾元素的递增子序列最后再加上ai;如果这样的元素不存在,那么自身构成一个长度为1的以ai为末尾元素的递增子序列。
代码
def f(arr):n = len(arr)dp = [0] * nfor i in range(n):dp[i] = 1for j in range(i):if arr[j] < arr[i]:dp[i] = max(dp[i], dp[j]+1)return dpdef generate_lis(arr, dp):n = max(dp)index = dp.index(n)lis = [0] * nn -= 1lis[n] = arr[index]# 从右向左查for i in range(index, -1, -1):if arr[i] < arr[index] and dp[i] == dp[index] - 1:n -= 1lis[n] = arr[i]index = ireturn lisif __name__ == '__main__':arr = [3, 1, 4, 5, 9, 2, 6, 5, 0]print(generate_lis(arr, f(arr)))
- 这种不确定向下查找的方向的不适合使用递归。
算法改进
- 上面那种解法的复杂度达到了O(n^2),其实可以改进为O(nlogn)。
- 在基本算法中,当需要计算前i个元素的最长递增子序列的时候,前i-1个元素作为最大元素的i-1个递增序列,无论是长度,还是最大元素值,都毫无规律,所以在开始计算前i个元素的时候只能遍历前i-1个元素,以找到满足的j值,使得aj<ai且满足条件的j中,以aj作为最大元素的递增子序列最长。
- 其实。在一个序列中,长度为n的递增子序列可能不只有一个,但是最大元素最小的递增子序列只有一个。上面例子中,当处理第7个元素“6“时,长度为2的子序列有两个,即{3,4}和{1,2},这个{1,2}就是最大元素最小的递增子序列。(可以轻易证明唯一性)随着序列长度的变化,满足条件的子序列不断变化。
- 如果将这些子序列安装长度由短到长排序,将每个序列的最大元素放在一起,形成新序列B{b1,b2,bj},则序列B一定是递增的。(此处不证明)
- 发现了这个严格递增,眼前一亮,可以利用此序列的严格递增进行二分查找,找到最大元素刚好小于aj的元素bk,将aj加入这个序列尾部,形成长度为k+1但是最大元素又小于b(k+1)的新序列,取代之前的b(k+1)。如果aj比B中所有元素都大,说明发现了以aj为最大元素,长度为n+1的递增序列,将aj作为B(n+1)的第n+1个元素。从b1依次递推,可以在O(nlogn)时间内找出A的最长递增子序列。
- 这种方法大幅度提高了运行效率。
- 优化代码见我的Github
补充说明
- 具体代码可以查看我的Github,欢迎Star或者Fork
- 参考书《你也能看得懂的Python算法书》,书中略微有一点不合理之处,做了修改
- 到这里,其实你已经体会到了动态规划的简约之美,当然,要注意Python是有递归深度限制的,如不是必要,建议使用循环控制
动态规划算法-04最长递增子序列问题相关推荐
- 用动态规划算法实现最长公共子序列问题的算法(java实现)
用动态规划算法实现最长公共子序列问题的算法 public class longestCommonSubsequence {//构造追踪数组rec,记录子问题来源private static Strin ...
- 【算法】最长递增子序列问题
1.问题描述 有一个序列 A = [18, 17, 19, 6, 11, 21, 23, 15],求出最长递增子序列的个数. 2.算法描述 该问题解唯一,但解的形式不唯一.譬如,该问题最长递增子序列的 ...
- 动态规划算法---求最长公共子序列
最长公共子序列和最长公共子串区别 最长公共子串(Longest Common Substring)与最长公共子序列(Longest Common Subsequence)的区别: 子串要 ...
- (算法)最长递增子序列
问题: Given an array of N integer, find the length of the longest increasing subsequence. For example, ...
- 【LeetCode 动态规划专项】最长递增子序列的个数(673)
文章目录 1. 题目 1.1 示例 1.2 说明 1.3 提示 1.4 进阶 2. 解法一(动态规划) 2.1 分析 2.1.1 定义状态 2.1.2 初始化状态 2.1.3 状态转移 2.1.4 返 ...
- 动态规划算法解最长公共子序列LCS问题
动态规划算法解LCS问题 作者 July 二零一零年十二月三十一日 本文参考:微软面试100题系列V0.1版第19.56题.算法导论.维基百科. 第一部分.什么是动态规划算法 ok,咱们先来了解下什么 ...
- leetcode算法题-- 最长递增子序列的个数★
原题链接:https://leetcode-cn.com/problems/number-of-longest-increasing-subsequence/ 相关题目:最长上升子序列 lengths ...
- 动态规划算法 | 最长递增子序列
通过查阅相关资料发现动态规划问题一般就是求解最值问题.这种方法在解决一些问题时应用比较多,比如求最长递增子序列等. 有部分人认为动态规划的核心就是:穷举.因为要求最值,肯定要把所有可行的答案穷举出来, ...
- 动态规划算法04-最长递增子序列问题
最长递增子序列问题 简述 经典的动态规划问题. 问题描述 给定一个序列,求解其中长度最长的递增子序列. 问题分析 这种可以向下查询答案的很容易想到动态规划的解法. 要求长度为i的序列Ai={a1,a2 ...
最新文章
- 【错误记录】IntelliJ IDEA 编译 Groovy 报错 ( GroovyRuntimeException: This script or class could not be run. )
- maven spring profile 协同
- 交通注意:叉车和自行车
- Golang学习笔记——Slice
- linux培训机构 网络班,Linux基础教程之网络基础知识与Linux网络配置
- LeetCode 241. 为运算表达式设计优先级(动态规划)
- 微信小程序(应用号)调试工具内测破解方法
- Spring:@Configuration和@Component的使用与区别
- 解决Windows Vista/7/8/8.1 远程桌面连接XP或2003缓慢的问题
- 【总结】动态规划 or 组合数学解决棋盘(迷宫)路径问题(持续更新中)
- yagmail发送附件
- linux下exe软件反编译工具下载,ilspy.exe
- 视频图像格式YUV详解
- Lua C API中文函数手册
- Linux环境下右键无法新建文档的解决方法——Ubuntu 16.x
- c语言null是什么意思,c语言null什么意思?
- 呕心编写的《金牌网管师——金牌网吧网管》
- 第27次CCF-CSP计算机软件能力认证(2022-09-18)
- 基于51单片机HX711的电子秤称重计价proteus仿真程序设计
- conda创建环境报错conda.core.subdir_data.Response304ContentUnchanged
热门文章
- MyBatis 实际使用案例-dataSource
- MybatisPlus性能分析插件
- 数据库-数据库的备份与恢复
- Hello Python程序演练
- SpringBoot_配置-@PropertySource、@ImportResource、@Bean
- 物理设计-如何存储日期类型
- 设计模式之_动态代理_03
- oracle与jdbc连接数据库,JDBC与Oracle数据库连接
- 【小题目】写JAVA程序时可以创建一个名为123.java的源文件吗
- 《CDN 之我见》原理篇——CDN的由来与调度