动态规划解决子序列问题:从LIS到最大子序和

发布时间:2026/11/6 4:34:16

动态规划解决子序列问题:从LIS到最大子序和 1. 动态规划在子序列问题中的应用概述动态规划Dynamic Programming是解决子序列问题的利器尤其擅长处理那些需要全局最优解的序列匹配问题。在算法领域子序列问题通常分为两大类连续子序列和非连续子序列。连续子序列要求元素在原序列中必须相邻而非连续子序列则允许元素之间存在间隔。动态规划解决这类问题的核心思想在于状态转移——通过定义合适的状态表示找出当前状态与之前状态之间的关系从而避免重复计算。对于子序列问题我们通常会定义dp[i]或dp[i][j]来表示以第i个元素结尾或考虑前i个元素时的某种最优解。2. 最长递增子序列问题解析300题2.1 问题定义与基本思路最长递增子序列Longest Increasing Subsequence, LIS问题要求在一个无序的整数序列中找到一个子序列使得这个子序列的元素严格递增并且这个子序列的长度尽可能长。这里的子序列不要求连续但必须保持原始顺序。例如对于序列[10,9,2,5,3,7,101,18]最长的递增子序列是[2,3,7,101]长度为4。2.2 动态规划解法详解2.2.1 DP数组定义我们定义dp[i]为以nums[i]结尾的最长递增子序列的长度。这个定义很关键它保证了我们只需要关注以当前元素结尾的情况而不用考虑全局。2.2.2 状态转移方程对于每个i我们需要检查所有j i的元素if nums[i] nums[j]: dp[i] max(dp[i], dp[j] 1)这个方程的含义是如果当前数字nums[i]比前面的某个数字nums[j]大那么我们可以把nums[i]接在以nums[j]结尾的子序列后面形成一个新的更长的子序列。2.2.3 初始化与遍历顺序每个dp[i]至少为1只包含自己所以初始化为全1数组。遍历顺序是外层循环i从1到n-1内层循环j从0到i-1。2.2.4 完整代码实现class Solution { public: int lengthOfLIS(vectorint nums) { if(nums.size() 1) return nums.size(); vectorint dp(nums.size(), 1); int result 1; for(int i 1; i nums.size(); i){ for(int j 0; j i; j){ if(nums[i] nums[j]){ dp[i] max(dp[i], dp[j] 1); } } result max(result, dp[i]); } return result; } };2.3 时间复杂度优化思路上述解法的时间复杂度是O(n²)对于大规模数据可能不够高效。更优的解法是使用贪心二分查找可以将时间复杂度降到O(nlogn)。基本思路是维护一个可能成为最长递增子序列的候选序列对于每个新元素用二分查找确定它的插入位置。3. 最长连续递增序列问题674题3.1 问题特点分析与300题不同674题要求子序列必须是连续的。这使得问题变得简单因为每个元素只需要与前一个元素比较而不需要与之前所有元素比较。3.2 动态规划解法3.2.1 DP数组定义dp[i]表示以nums[i]结尾的最长连续递增子序列的长度。3.2.2 状态转移方程if nums[i] nums[i-1]: dp[i] dp[i-1] 1 else: dp[i] 13.2.3 代码实现class Solution { public: int findLengthOfLCIS(vectorint nums) { if(nums.empty()) return 0; vectorint dp(nums.size(), 1); int result 1; for(int i 1; i nums.size(); i){ if(nums[i] nums[i-1]){ dp[i] dp[i-1] 1; result max(result, dp[i]); } } return result; } };3.3 空间优化技巧由于dp[i]只依赖于dp[i-1]我们可以用一个变量代替整个dp数组将空间复杂度从O(n)降到O(1)。4. 最长重复子数组问题718题4.1 二维动态规划解法4.1.1 DP数组定义定义dp[i][j]为以A[i-1]和B[j-1]结尾的最长公共子数组的长度。这里使用i-1和j-1是为了方便处理边界条件。4.1.2 状态转移方程if A[i-1] B[j-1]: dp[i][j] dp[i-1][j-1] 1 else: dp[i][j] 04.1.3 代码实现class Solution { public: int findLength(vectorint nums1, vectorint nums2) { int m nums1.size(), n nums2.size(); vectorvectorint dp(m1, vectorint(n1, 0)); int result 0; for(int i 1; i m; i){ for(int j 1; j n; j){ if(nums1[i-1] nums2[j-1]){ dp[i][j] dp[i-1][j-1] 1; result max(result, dp[i][j]); } } } return result; } };4.2 空间优化技巧由于dp[i][j]只依赖于左上方的dp[i-1][j-1]我们可以将二维DP优化为一维通过逆序遍历j来避免覆盖。5. 最长公共子序列问题1143题5.1 与重复子数组的区别最长公共子序列LCS不要求连续这是与718题的主要区别。这使得状态转移方程需要考虑更多情况。5.2 动态规划解法5.2.1 DP数组定义dp[i][j]表示text1前i个字符和text2前j个字符的最长公共子序列长度。5.2.2 状态转移方程if text1[i-1] text2[j-1]: dp[i][j] dp[i-1][j-1] 1 else: dp[i][j] max(dp[i-1][j], dp[i][j-1])5.2.3 代码实现class Solution { public: int longestCommonSubsequence(string text1, string text2) { int m text1.size(), n text2.size(); vectorvectorint dp(m1, vectorint(n1, 0)); for(int i 1; i m; i){ for(int j 1; j n; j){ if(text1[i-1] text2[j-1]){ dp[i][j] dp[i-1][j-1] 1; }else{ dp[i][j] max(dp[i-1][j], dp[i][j-1]); } } } return dp[m][n]; } };6. 不相交的线问题1035题6.1 问题转化思路1035题实际上是1143题的变种因为绘制不相交的连线等价于找到两个序列的最长公共子序列。相同的数字可以连接且顺序必须保持一致。6.2 解法实现可以直接使用1143题的解法因为两者本质相同。7. 最大子序和问题53题7.1 动态规划解法7.1.1 DP数组定义dp[i]表示以nums[i]结尾的最大子序和。7.1.2 状态转移方程dp[i] max(nums[i], dp[i-1] nums[i])7.1.3 代码实现class Solution { public: int maxSubArray(vectorint nums) { int n nums.size(); if(n 0) return 0; vectorint dp(n); dp[0] nums[0]; int result dp[0]; for(int i 1; i n; i){ dp[i] max(nums[i], dp[i-1] nums[i]); result max(result, dp[i]); } return result; } };7.2 空间优化同样可以优化为O(1)空间只需维护前一个状态的dp值。8. 动态规划解题方法论总结8.1 解题通用步骤定义DP数组的含义确定初始条件推导状态转移方程确定遍历顺序考虑空间优化8.2 常见错误与调试技巧边界条件处理不当特别注意数组为空或只有一个元素的情况DP数组初始化错误根据问题需求正确初始化遍历顺序错误确保计算当前状态时所需的前置状态已经计算结果提取位置错误有时结果不是dp[n-1]需要在遍历过程中记录最大值8.3 不同问题的对比分析问题类型连续性要求状态转移特点典型例题最长递增子序列非连续需要比较前面所有元素300题最长连续递增序列连续只需比较前一个元素674题最长重复子数组连续二维DP相等时从左上角转移718题最长公共子序列非连续二维DP不等时考虑左或上1143题最大子序和连续一维DP选择是否接上前面的和53题在实际面试和解题过程中理解这些问题的共性和差异能够帮助我们快速识别问题类型并选择合适的解法。动态规划虽然有一定难度但通过大量练习和总结可以掌握其核心思想并灵活应用。
延伸阅读

更多相关文章

2026/11/6 4:29:16

数据库连接操作详解:从内连接到外连接

1. 数据库连接操作的本质理解在数据库查询中,连接(Join)操作就像是在两个数据表之间搭建桥梁。想象你手上有两份Excel表格:一份记录着公司所有员工的基本信息,另一份存储着各部门的绩效数据。当我们需要分析"每个…

2026/11/6 4:29:16

肌电放大器设计核心:共模抑制比与增益分配的工程平衡

简介:本资源是一份面向生物医学工程、电子电路设计及嵌入式信号采集方向初学者与课程实验者的肌电放大器专项学习材料,聚焦微弱生理信号检测中的核心电路设计与仿真验证问题。内容涵盖肌电信号特性分析(50μV~2mV幅值、10&#xf…

2026/11/6 4:29:16

TCP套接字关闭:close()与shutdown()的本质区别与应用

1. TCP套接字关闭操作的本质区别在TCP网络编程中,close()和shutdown()这两个系统调用看似都能关闭连接,但底层机制和适用场景存在本质差异。我在处理高并发网络服务时,曾因混淆两者特性导致连接泄漏和异常断开问题,后来通过抓包分…

2026/11/6 5:49:24

OceanBase与DataGrip连接配置与优化实战

1. OceanBase与DataGrip技术栈解析作为国产分布式数据库的代表作,OceanBase凭借其高可用性和水平扩展能力,在金融、电信等领域逐步替代传统Oracle架构。而JetBrains旗下的DataGrip作为多数据库管理工具,其智能补全、可视化查询等功能深受开发…

2026/11/6 5:49:24

高并发场景下的缓存架构设计与实践

1. 缓存架构设计的核心挑战与误区在当今互联网应用中,缓存早已成为提升系统性能的标准配置。但很多开发者对缓存的理解仍停留在"加一层Redis"的初级阶段,这种认知在实际高并发场景下往往捉襟见肘。我曾负责过一个日活超过300万的电商平台架构优…

2026/11/6 5:49:24

C++ vector核心原理与高效使用指南

1. 为什么每个C开发者都需要掌握vector在C标准库的众多容器中,vector就像瑞士军刀一样不可或缺。作为动态数组的完美实现,它结合了数组的高效随机访问和动态内存管理的灵活性。我见过太多初级开发者还在手动管理动态数组,每次看到new[]和dele…

2026/11/6 5:49:24

单分流无感FOC实战:PMSM电流重构与启动调试

简介:面向汽车电机控制开发者的AN5327应用笔记,聚焦三相无传感器、单分流电阻电流采样的永磁同步电机矢量控制方案。内容围绕MC9S12ZVM器件展开,讲解磁场定向控制原理、dq坐标系电机模型、输出电压激励与相电流测量、转子位置与速度估算&…

2026/11/6 5:49:24

Kafka消费者组重平衡机制与重复消费问题解析

1. Kafka消费者组重平衡机制深度解析在现代分布式系统中,Kafka作为核心的消息中间件,其消费者组机制是实现高吞吐、高可用的关键设计。消费者组重平衡(Rebalance)是保证这一机制正常运转的核心过程,但同时也是系统稳定…

2026/11/6 5:44:23

UReport2集成Spring Boot:报表设计器、数据源与存储避坑手册

简介:面向Java后端开发者的一份UReport报表工具实践材料,围绕UReport2的环境搭建与报表制作展开,适合需要在Spring Boot项目中快速接入报表导出能力的初中级开发者参考。压缩包内仅含1个doc文件,体积约1.15MB,正文串联…

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/6 1:03:39

MCU晶振电路设计全解析:从负载电容计算到PCB布局调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑