【算法】动态规划专题② ——LIS(最长递增子序列) python

server/2025/2/5 5:55:33/

目录

  • 前置知识
  • 问题描述
  • DP解法
  • 小试牛刀
  • 举一反三
  • 实战演练
  • 总结


前置知识


算法动态规划专题① ——线性DP python


问题描述


题目是说:
给定一个整数数组,找到其中最长的严格递增子序列的长度。(子序列不要求连续)

比如说,像数组 [10,9,2,5,3,7,101,18],最长递增子序列是 [2,5,7,101],所以长度是4。

那要怎么做呢?


DP解法


对于每个元素,遍历它前面的所有元素,如果前面的元素比它小,那么就可以在这个元素的基础上形成更长的子序列。
再维护一个dp数组,其中dp[ i i i]表示以第 i i i个元素结尾的最长子序列的长度

那具体步骤是怎么样的呢?

初始化dp[ i i i]=1,然后,
对于每个 i i i,从 j j j=0到 i i i-1遍历,
如果nums[ i i i] > nums[ j j j],那么dp[ i i i] = max(dp[ i i i], dp[ j j j] + 1)。

这样处理完所有元素之后,最大的dp值就是结果。


比如上面的例子,数组是[10,9,2,5,3,7,101,18],对应的dp数组应该怎么算?

初始dp都是1。第一个元素10,前面没有元素,dp[0]=1。第二个元素9,比10小,所以不能接在后面,所以dp[1]=1。第三个元素2,同样比前面两个都小,所以dp[2]=1。第四个元素5,前面有元素2,所以dp[3] = dp[2]+1=2。接下来第五个元素3,比它前面的一些元素大吗?比如,3比2大,所以dp[4] = dp[2]+1=2。第六个元素7,前面比它小的有2、5、3,所以这时候要看这些位置上的dp值加1的最大值。比如,2对应的dp是1,5对应的dp是2,3对应的dp是2。所以最大的加1是3,所以dp[5]=3。第七个元素101,前面所有比它小的元素对应的dp值的最大值是3,所以dp[6]=4。最后一个元素18,前面比它小的元素中最大的dp值可能是3(比如7的位置),所以dp[7] =4。那么最大的dp是4,即答案为4。


示例:

python">a = [10, 9, 2, 5, 3, 7, 101, 18]
n = len(a)
dp = [0] * n
for i in range(n):dp[i] = 1  # 单独一个元素本身就是一个长度为1的子序列for j in range(i):if a[j] < a[i]:dp[i] = max(dp[i], dp[j] + 1)
print(max(dp))  # 4(2,3,7,101)


小试牛刀


蓝桥勇士 https://www.lanqiao.cn/problems/2049/learning/?page=1&first_category_id=1&problem_id=2049


题目描述

小明是蓝桥王国的勇士,他晋升为蓝桥骑士,于是他决定不断突破自我。
这天蓝桥首席骑士长给他安排了N个对手,他们的战力值分别为a1,a2,an,且按顺序阻挡在小明的前方。对于这些对手小明可以选择挑战,也可以选择避战。
作为热血豪放的勇士,小明从不走回头路,且只愿意挑战战力值越来越高的对手。
请你算算小明最多会挑战多少名对手。

输入描述:
输入第一行包含一个整数N,表示对手的个数。
第二行包含N个整数a1,a2,······,an,分别表示对手的战力值。
1≤N≤1e3,1≤a≤1e9。

输出描述:
输出一行整数表示答案。

示例输入:

6
1 4 3 2 5 6

示例输出:

4

code实现:

python">n = int(input())
a = list(map(int, input().split()))
dp = [0] * n
for i in range(n):dp[i] = 1 for j in range(i):if a[j] < a[i]:dp[i] = max(dp[i], dp[j] + 1)
ans = max(dp)
print(ans)



举一反三


既然有最长递增子序列,那是不是也得有最长下降子序列
这又该怎么求呢?

类似地:

python">a = [10, 9, 2, 5, 3, 7, 101, 18]
n = len(a)
dp = [0] * n
for i in range(n - 1, -1, -1):dp[i] = 1for j in range(i + 1, n):if a[i] > a[j]:dp[i] = max(dp[i], dp[j] + 1)
print(max(dp))  # 4(10,9,5,3)


好了,实际运用的时候到了

实战演练


合唱队形 https://www.lanqiao.cn/problems/742/learning/?page=1&first_category_id=1&problem_id=742

题目描述

N位同学站成一排,音乐老师要请其中的(N一K)位同学出列,使得剩下的K位同学排成合唱队形。

合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2,······K,他们的身高分别为T1,T2,······,TK,则他们的身高满足
T1<···Ti+1>···>Tk(1≤i≤K)。

你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

输入描述

输入两行
第一行是一个整数N(2≤N≤100),表示同学的总数。
第二行有n个整数,用空格分隔,第i个整数Ti(130≤T≤230)是第i位同学的身高(厘米)。

输出描述

输出一个整数,就是最少需要几位同学出列。

示例输入:

8
186 186 150 200 160 130 197 220 

示例输出:

4

思路分析:

求出最长递增子序列和最长下降子序列相加的最大值 -1 即可


题解code:

python">n = int(input())
a = list(map(int, input().split()))dp1 = [0] * n
dp2 = [0] * n
for i in range(n):dp1[i] = 1for j in range(i):if a[i] > a[j]:dp1[i] = max(dp1[i], dp1[j] + 1)for i in range(n - 1, -1, -1):dp2[i] = 1for j in range(i + 1, n):if a[i] > a[j]:dp2[i] = max(dp2[i], dp2[j] + 1)res = max(dp1[x] + dp2[x] - 1 for x in range(n))
print(n - res)


总结


动态规划解法以清晰的逻辑展现 LIS (最长递增子序列)问题的递推本质,是算法学习的经典案例。
当然,此解法时间复杂度是O(n^2),当n较大时,比如1e4或1e5,会超时。
那有没有更优的解法?比如O(n log n)的解法?
答案是有的。二分 + 贪心 的做法,
不过在此就不多赘述了,感兴趣的可以自己思考一下。


END
如果有更多问题或需要进一步的帮助,可以在评论区留言讨论哦!
如果喜欢的话,请给博主点个关注 谢谢


http://www.ppmy.cn/server/165080.html

相关文章

数据结构——并查集

一、并查集原理 再一些应用问题中&#xff0c;需要将n个不同的元素划分成一些不相交的集合。开始时&#xff0c;每个元素自成一个单元素集合&#xff0c;然后按一定的规律将归于同一组元素的集合合并。在此过程中要反复用到查询某一个元素归属于哪个集合。适合这种问题的抽象…

javascript-es6 (一)

作用域&#xff08;scope&#xff09; 规定了变量能够被访问的“范围”&#xff0c;离开了这个“范围”变量便不能被访问 局部作用域 函数作用域&#xff1a; 在函数内部声明的变量只能在函数内部被访问&#xff0c;外部无法直接访问 function getSum(){ //函数内部是函数作用…

Vue.js组件开发-实现全屏焦点图片带图标导航按钮控制图片滑动切换

使用 Vue 实现全屏焦点图片带图标导航按钮控制图片滑动切换 步骤 创建 Vue 项目&#xff1a;可以使用 Vue CLI 快速创建一个新的 Vue 项目。设计组件结构&#xff1a;创建一个包含图片展示区域和导航按钮的组件。实现图片滑动切换逻辑&#xff1a;通过点击导航按钮切换图片。…

深入核心:一步步手撕Tomcat搭建自己的Web服务器

介绍&#xff1a; servlet&#xff1a;处理 http 请求 tomcat&#xff1a;服务器 Servlet servlet 接口&#xff1a; 定义 Servlet 声明周期初始化&#xff1a;init服务&#xff1a;service销毁&#xff1a;destory 继承链&#xff1a; Tomcat Tomcat 和 servlet 原理&#x…

简单的SQL语句的快速复习

语法的执行顺序 select 4 字段列表 from 1 表名列表 where 2 条件列表 group by 3 分组前过滤 having 分组后过滤 order by 5 排序字段列表 limit 6 分页参数 聚合函数 count 统计数量 max 最大值 min 最小值 avg 平均 sum 总和 分组查询使…

AJAX笔记原理篇

黑马程序员视频地址&#xff1a; AJAX-Day03-01.XMLHttpRequest_基本使用https://www.bilibili.com/video/BV1MN411y7pw?vd_source0a2d366696f87e241adc64419bf12cab&spm_id_from333.788.videopod.episodes&p33https://www.bilibili.com/video/BV1MN411y7pw?vd_sour…

3D图形学与可视化大屏:什么是材质属性,有什么作用?

一、颜色属性 漫反射颜色 漫反射颜色决定了物体表面对入射光进行漫反射后的颜色。当光线照射到物体表面时&#xff0c;一部分光被均匀地向各个方向散射&#xff0c;形成漫反射。漫反射颜色的选择会直接影响物体在光照下的外观。例如&#xff0c;一个红色的漫反射颜色会使物体在…

Linux+Docer 容器化部署之 Shell 语法入门篇 【Shell 循环类型】

文章目录 一、Shell 循环类型二、Shell while 循环三、Shell for 循环四、Shell until 循环五、Shell select 循环六、总结 一、Shell 循环类型 循环是一个强大的编程工具&#xff0c;使您能够重复执行一组命令。在本教程中&#xff0c;您将学习以下类型的循环 Shell 程序&…