动态规划:最长递增子序列

给定一个数组,求最长递增子序列的长度,就是要求我们求出一个序列中最长的上升子序列的长度,最长上升子序列的定义就是从原序列中按照孙旭去除一些数字,这些数字是逐渐增大的。

*定义dp[i]表示以第i个元素结尾的最长上升子序列的长度。

*初始时,每个dp[i]的值至少为1,因为每个元素本身就是一个长度为1的上升子序列

*对于每个元素i,我们遍历起前面的所有元素j,如果nums[i] < nums[j],则更新

dp[i] = max(dp[i],dp[j] + 1)

*最终,最长上升子序列的长度就是dp数组中的最大值。

函数逻辑

  1. 输入与边界处理

    • 输入为整数向量 nums

    • 若数组为空(n == 0),直接返回 0。

  2. 动态规划初始化

    • 创建长度为 n 的数组 dp,初始值全为 1。dp[i] 表示以 nums[i] 结尾的最长递增子序列的长度(每个元素自身至少构成长度为 1 的子序列)。

  3. 动态规划递推

    • 外层循环遍历每个元素 nums[i](从第 2 个元素开始)。

    • 内层循环遍历 nums[i] 之前的所有元素 nums[j]j < i)。

    • 若 nums[j] < nums[i],说明可以将 nums[i] 接在 nums[j] 对应的递增子序列后。此时更新 dp[i] 为 max(dp[i], dp[j] + 1),确保 dp[i] 记录当前最长长度。

  4. 返回结果

    • 最终返回 dp 数组中的最大值,即整个数组的最长递增子序列长度。

示例验证

以输入 [10, 9, 2, 5, 3, 7, 101, 18] 为例:

  • dp 数组逐步更新为 [1, 1, 1, 2, 2, 3, 4, 4]

  • 最大值为 4,对应最长递增子序列如 [2, 5, 7, 101]

复杂度分析

  • 时间复杂度:O(n²),两层嵌套循环遍历所有元素对。

  • 空间复杂度:O(n),用于存储 dp 数组。

#include <iostream>
#include <vector>
#include <algorithm> // 用于max_elementusing namespace std;/*** 使用动态规划求最长递增子序列长度* @param nums 输入数组* @return 最长递增子序列的长度*/
int lengthOfLIS(vector<int>& nums) {int n = nums.size();if (n == 0) return 0;// dp[i]表示以nums[i]结尾的最长递增子序列的长度vector<int> dp(n, 1); // 初始化为1,每个元素自身就是一个子序列for (int i = 1; i < n; ++i) {for (int j = 0; j < i; ++j) {if (nums[j] < nums[i]) {// 如果nums[j] < nums[i],则可以扩展子序列dp[i] = max(dp[i], dp[j] + 1);}}}// 返回dp数组中的最大值return *max_element(dp.begin(), dp.end());
}/*** 输出最长递增子序列本身(而不仅仅是长度)* @param nums 输入数组* @return 最长递增子序列*/
vector<int> getLIS(vector<int>& nums) {int n = nums.size();if (n == 0) return {};vector<int> dp(n, 1);vector<int> prev(n, -1); // 用于记录前驱元素索引for (int i = 1; i < n; ++i) {for (int j = 0; j < i; ++j) {if (nums[j] < nums[i] && dp[j] + 1 > dp[i]) {dp[i] = dp[j] + 1;prev[i] = j; // 记录前驱}}}// 找到dp数组中最大值的索引int max_len = 0, max_index = 0;for (int i = 0; i < n; ++i) {if (dp[i] > max_len) {max_len = dp[i];max_index = i;}}// 回溯构建LISvector<int> lis;while (max_index != -1) {lis.push_back(nums[max_index]);max_index = prev[max_index];}reverse(lis.begin(), lis.end()); // 反转得到正确顺序return lis;
}int main() {vector<int> nums = {10, 9, 2, 5, 3, 7, 101, 18};// 计算并输出最长递增子序列长度int length = lengthOfLIS(nums);cout << "最长递增子序列长度: " << length << endl;// 获取并输出最长递增子序列本身vector<int> lis = getLIS(nums);cout << "最长递增子序列: ";for (int num : lis) {cout << num << " ";}cout << endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/80210.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

湖北理元理律师事务所:债务优化如何实现还款与生活的平衡?

债务压力往往让债务人陷入“还款还是生存”的两难选择。湖北理元理律师事务所通过案例实践发现&#xff0c;科学规划的核心在于平衡法律义务与基本生活保障&#xff0c;而非单纯追求债务缩减。本文结合实务经验&#xff0c;解析债务优化的可行路径。 刚性需求优先&#xff1a;…

重力场模型、球谐函数以及重力异常

地球重力场有两种表达方法&#xff1a; 1、拉普拉斯&#xff08;Laplace&#xff09;方法&#xff0c;将重力场展开为球谐级数。 2、斯托克斯&#xff08;Stokes&#xff09;方法&#xff0c;根据地球的总质量和旋转角速度计算。 本篇主要说第一种方法&#xff0c;该方法将地…

MySQL的视图

一、MySQL视图的介绍和作用 MySQL视图&#xff0c;加油兄弟们&#xff0c;孰能生巧&#xff0c;完整代码在最后&#xff01;&#xff01;&#xff01; 视图是一个虚拟的表&#xff0c;并不是真是存在的&#xff0c;视图其实并没有真实的数据&#xff0c;他只是根据一个sql语句…

Scala与Go的异同教程

当瑞士军刀遇到电锯&#xff1a;Scala vs Go的相爱相杀之旅 各位准备秃头的程序猿们&#xff08;放心&#xff0c;用Go和Scala不会加重你的发际线问题&#xff09;&#xff0c;今天我们来聊聊编程界的"冰与火之歌"——Scala和Go的异同。准备好瓜子饮料&#xff0c;我…

SaaS场快订平台项目说明【持续更新】

一、项目介绍 SaaS场快订平台是一个高效、便捷的体育场馆在线预订平台。本项目采用SaaS方式开发&#xff0c;用户不需要安装软件&#xff0c;直接通过互联网访问在线程序即可使用。本项目主要构建了一个体育馆预订系统&#xff0c;项目的功能主要包括&#xff1a;用户注册与登…

linux中常用的命令(三)

目录 1- ls(查看当前目录下的内容) 2- pwd (查看当前所在的文件夹) 3- cd [目录名]&#xff08;切换文件夹&#xff09; 4- touch [文件名] &#xff08;如果文件不存在&#xff0c;新建文件&#xff09; 5- mkdir[目录名] &#xff08;创建目录&#xff09; 6-rm[文件名]&…

使用Simulink开发Autosar Nvm存储逻辑

文章目录 前言Autosar Nvm接口设计模型及接口生成代码及arxmlRTE接口mappingRTE代码分析总结 前言 之前介绍过Simulink开发Dem故障触发逻辑&#xff0c;本文接着介绍另外一个常用的功能-Nvm存储的实现。 Autosar Nvm接口 Autosar Nvm中一般在上电初始化的时调用Nvm_ReadAll获…

Java—— 泛型详解

泛型概述 泛型是JDK5中引入的特性&#xff0c;可以在编译阶段约束操作的数据类型&#xff0c;并进行检查。 泛型的格式&#xff1a;<数据类型> 注意&#xff1a;泛型只能支持引用数据类型。 泛型的好处 没有泛型的时候&#xff0c;可以往集合中添加任意类型的数据&#x…

通俗的桥接模式

桥接模式&#xff08;Bridge Pattern&#xff09; 就像一座桥&#xff0c;把两个原本独立变化的东西连接起来&#xff0c;让它们可以各自自由变化&#xff0c;互不干扰。简单来说&#xff0c;就是 “把抽象和实现分开&#xff0c;用组合代替继承”。 一句话理解桥接模式 假设你…

【现代深度学习技术】注意力机制04:Bahdanau注意力

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈PyTorch深度学习 ⌋ ⌋ ⌋ 深度学习 (DL, Deep Learning) 特指基于深层神经网络模型和方法的机器学习。它是在统计机器学习、人工神经网络等算法模型基础上&#xff0c;结合当代大数据和大算力的发展而发展出来的。深度学习最重…

爬虫学习————开始

&#x1f33f;自动化的思想 任何领域的发展原因————“不断追求生产方式的改革&#xff0c;即使得付出与耗费精力越来愈少&#xff0c;而收获最大化”。由此&#xff0c;创造出方法和设备来提升效率。 如新闻的5W原则直接让思考过程规范化、流程化。或者前端框架/后端轮子的…

每天五分钟机器学习:KTT条件

本文重点 在前面的课程中,我们学习了拉格朗日乘数法求解等式约束下函数极值,如果约束不是等式而是不等式呢?此时就需要KTT条件出手了,KTT条件是拉格朗日乘数法的推广。KTT条件不仅统一了等式约束与不等式约束的优化问题求解范式,KTT条件给出了这类问题取得极值的一阶必要…

leetcode0829. 连续整数求和-hard

1 题目&#xff1a; 连续整数求和 官方标定难度&#xff1a;难 给定一个正整数 n&#xff0c;返回 连续正整数满足所有数字之和为 n 的组数 。 示例 1: 输入: n 5 输出: 2 解释: 5 2 3&#xff0c;共有两组连续整数([5],[2,3])求和后为 5。 示例 2: 输入: n 9 输出: …

window 显示驱动开发-线性伸缩空间段

线性伸缩空间段类似于线性内存空间段。 但是&#xff0c;伸缩空间段只是地址空间&#xff0c;不能容纳位。 若要保存位&#xff0c;必须分配系统内存页&#xff0c;并且必须重定向地址空间范围以引用这些页面。 内核模式显示微型端口驱动程序&#xff08;KMD&#xff09;必须实…

Cadence 高速系统设计流程及工具使用三

5.8 约束规则的应用 5.8.1 层次化约束关系 在应用约束规则之前&#xff0c;我们首先要了解这些约束规则是如何作用在 Cadence 设计对象上的。Cadence 中对设计对象的划分和概念&#xff0c;如表 5-11 所示。 在 Cadence 系统中&#xff0c;把设计对象按层次进行了划分&#…

ScaleTransition 是 Flutter 中的一个动画组件,用于实现缩放动画效果。

ScaleTransition 是 Flutter 中的一个动画组件&#xff0c;用于实现缩放动画效果。它允许你对子组件进行动态的缩放变换&#xff0c;从而实现平滑的动画效果。ScaleTransition 通常与 AnimationController 和 Tween 一起使用&#xff0c;以控制动画的开始、结束和过渡效果。 基…

深入解析:如何基于开源p-net快速开发Profinet从站服务

一、Profinet协议与软协议栈技术解析 1.1 工业通信的"高速公路" Profinet作为工业以太网协议三巨头之一,采用IEEE 802.3标准实现实时通信,具有: 实时分级:支持RT(实时)和IRT(等时实时)通信模式拓扑灵活:支持星型、树型、环型等多种网络结构对象模型:基于…

m个n维向量组中m,n的含义与空间的关系

向量的维度与空间的关系&#xff1a; 一个向量的维度由其分量个数决定&#xff0c;例如 ( n ) 个分量的向量属于 Rn空间 。 向量组张成空间的维度&#xff1a; 当向量组有 ( m ) 个线性无关的 ( n ) 维向量时&#xff1a; 若 ( m < n )&#xff1a; 这些向量张成的是 Rn中的…

excel大表导入数据库

前文介绍了数据量较小的excel表导入数据库的方法&#xff0c;在数据量较大的情况下就不太适合了&#xff0c;一个是因为mysql命令的执行串长度有限制&#xff0c;二是node-xlsx这个模块加载excel文件是整个文件全部加载到内存&#xff0c;在excel文件较大和可用内存受限的场景就…

Python 爬虫基础入门教程(超详细)

一、什么是爬虫&#xff1f; 网络爬虫&#xff08;Web Crawler&#xff09;&#xff0c;又称网页蜘蛛&#xff0c;是一种自动抓取互联网信息的程序。爬虫会模拟人的浏览行为&#xff0c;向网站发送请求&#xff0c;然后获取网页内容并提取有用的数据。 二、Python爬虫的基本原…