当前位置: 首页 > news >正文

LeetCode刷题实战:用Python搞定最长递增子序列和最大子数组和(附完整代码)

LeetCode刷题实战:Python动态规划解决最长递增子序列与最大子数组和

1. 动态规划基础与问题识别

动态规划(Dynamic Programming)是算法面试中的高频考点,尤其适合解决具有重叠子问题和最优子结构特性的问题。在LeetCode中,线性动态规划问题占据了相当大的比重,其中最长递增子序列(LIS)和最大子数组和(Maximum Subarray)是两类经典问题。

识别动态规划问题的关键特征:

  • 最优子结构:问题的最优解包含子问题的最优解
  • 重叠子问题:递归算法会重复计算相同的子问题
  • 状态转移:当前状态可以由之前的状态推导出来

对于线性DP问题,我们通常使用一维或二维数组来存储中间状态,其中:

  • dp[i]表示以第i个元素结尾的子问题的解
  • dp[i][j]表示涉及两个序列时,第一个序列前i个元素和第二个序列前j个元素的解

提示:在面试中,90%的动态规划问题都可以用一维或二维DP数组解决,关键在于正确定义状态。

2. 最长递增子序列(LIS)问题详解

2.1 问题描述与状态定义

LeetCode 300题要求找到数组中最长的严格递增子序列长度。子序列不要求连续,但必须保持原始顺序。

例如:

输入:[10,9,2,5,3,7,101,18] 输出:4 # 最长递增子序列是[2,3,7,101]

状态定义

  • dp[i]:以nums[i]结尾的最长递增子序列长度

2.2 状态转移方程与实现

对于每个元素nums[i],我们需要检查所有之前的元素nums[j](j < i):

if nums[i] > nums[j]: dp[i] = max(dp[i], dp[j] + 1)

完整Python实现:

def lengthOfLIS(nums): if not nums: return 0 dp = [1] * len(nums) for i in range(1, len(nums)): for j in range(i): if nums[i] > nums[j]: dp[i] = max(dp[i], dp[j] + 1) return max(dp)

复杂度分析

  • 时间复杂度:O(n²) - 双重循环
  • 空间复杂度:O(n) - 一维DP数组

2.3 优化策略:二分查找法

对于大规模数据(n>10⁴),O(n²)的解法会超时。我们可以使用贪心+二分查找将复杂度降至O(nlogn):

def lengthOfLIS(nums): tails = [] for num in nums: left, right = 0, len(tails) while left < right: mid = (left + right) // 2 if tails[mid] < num: left = mid + 1 else: right = mid if left == len(tails): tails.append(num) else: tails[left] = num return len(tails)

这种方法维护一个tails数组,其中tails[i]表示长度为i+1的所有递增子序列的最小末尾元素。

3. 最大子数组和问题解析

3.1 问题描述与状态定义

LeetCode 53题要求找到一个具有最大和的连续子数组(子数组最少包含一个元素)。

例如:

输入:[-2,1,-3,4,-1,2,1,-5,4] 输出:6 # 子数组[4,-1,2,1]的和最大

状态定义

  • dp[i]:以nums[i]结尾的最大子数组和

3.2 状态转移与实现

关键观察:当前元素要么加入前面的子数组,要么自己另起一个新子数组:

dp[i] = max(nums[i], dp[i-1] + nums[i])

Python实现:

def maxSubArray(nums): if not nums: return 0 dp = [0] * len(nums) dp[0] = nums[0] for i in range(1, len(nums)): dp[i] = max(nums[i], dp[i-1] + nums[i]) return max(dp)

复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

3.3 空间优化:滚动数组

由于dp[i]只依赖于dp[i-1],我们可以用单个变量代替DP数组:

def maxSubArray(nums): if not nums: return 0 max_sum = current_sum = nums[0] for num in nums[1:]: current_sum = max(num, current_sum + num) max_sum = max(max_sum, current_sum) return max_sum

优化后的空间复杂度为O(1),这是面试官最希望看到的解法。

4. 两种DP问题的对比与实践技巧

4.1 关键差异对比

特性最长递增子序列 (LIS)最大子数组和
子序列/子数组不要求连续必须连续
典型状态定义dp[i]以nums[i]结尾的LISdp[i]以nums[i]结尾的最大和
时间复杂度O(n²)或O(nlogn)O(n)
空间复杂度O(n)O(1)优化后
转移方程特点需要遍历之前所有元素只需考虑前一个状态

4.2 刷题实战建议

  1. 模板化思考:对于DP问题,先明确:

    • 状态定义
    • 初始条件
    • 状态转移方程
    • 最终结果如何从DP数组中提取
  2. 常见错误

    • 混淆子序列和子数组的概念
    • 初始化不正确(特别是边界条件)
    • 没有进行空间优化(面试加分项)
  3. 测试用例设计

    • 空数组
    • 单元素数组
    • 全正/全负数组
    • 有重复元素的数组
# LIS测试用例示例 test_cases = [ ([], 0), ([1], 1), ([1,3,2,4], 3), ([10,9,2,5,3,7,101,18], 4) ] # 最大子数组和测试用例 test_cases = [ ([], 0), ([-1], -1), ([-2,1,-3,4,-1,2,1,-5,4], 6), ([5,4,-1,7,8], 23) ]

4.3 进阶挑战

掌握了这两个基础问题后,可以尝试以下变种:

  1. LIS变种

    • 输出具体的LIS而不仅是长度
    • 二维LIS问题(如LeetCode 354. 俄罗斯套娃信封问题)
  2. 最大子数组和变种

    • 环形数组的最大子数组和(LeetCode 918)
    • 乘积最大子数组(LeetCode 152)

注意:在解决变种问题时,核心DP思想不变,但需要根据题目要求调整状态定义和转移方程。

http://www.jsqmd.com/news/687357/

相关文章:

  • 软件数据访问对象管理化的持久化抽象
  • GStreamer管道设计避坑指南:从USB摄像头采集到H.264 MP4,这些参数你调对了吗?
  • 哔哩下载姬完整指南:如何轻松获取B站高清视频资源
  • 告别pip install失败:用Anaconda虚拟环境丝滑部署TensorFlow-GPU(附国内源加速配置)
  • 2026年不错的二手车行企业推荐,杭州哪家品牌 - 工业推荐榜
  • MSP430开发入门:手把手教你用IAR EW430创建第一个工程(含F5529配置与常见下载错误解决)
  • EasyExcel单元格染色避坑指南:IndexedColors vs 自定义RGB,哪个更适合你的业务?
  • ERPNext无人值守安装脚本:如何5分钟完成企业级ERP系统部署
  • 最新YOLO实现的钢材表面缺陷实时检测平台(Flask+SocketIO+HTML_CSS_JS)
  • 别再手动折腾DLL了!用Winetricks一键搞定Linux下Wine环境配置(附QQ安装实战)
  • 从原理到优化:深入拆解Cesium自定义材质实现水面倒影的Shader技巧
  • 全自动微信聊天+公域获客+短视频分发,智能数字员工系统源码分享
  • 最新YOLO实现的草莓成熟度实时检测平台(Flask+SocketIO+HTML_CSS_JS)
  • Jetson Xavier NX 上唯一那个CAN口到底在哪?别再照着老教程找40针了
  • d2s-editor:5分钟掌握暗黑破坏神2存档修改技巧
  • 哪款雅思机考软件提供完整成绩报告?2026备考工具实测推荐 - 品牌2026
  • AI政策路径推演:凯文·沃什延迟上任情境下的鲍威尔留任机制分析
  • 别再纠结选哪种深度相机了!立体视觉、结构光、TOF,看完这篇保姆级对比你就懂了
  • 为什么 LINUX DO 突然这么火?一个程序员拆解背后的5个互联网逻辑
  • LIN总线测试避坑指南:详解linInvertRespBit与linInvertHeaderBit在数据场/校验位干扰中的区别与应用
  • Jellyfin Kodi插件终极指南:打造无缝家庭影院体验的5个关键步骤
  • 5分钟掌握Diff Checker:终极免费文本差异对比工具使用指南
  • iOSDeviceSupport:Xcode设备调试兼容性问题的终极解决方案
  • 告警管理化技术告警收敛与通知策略
  • 保姆级教程:用iwpriv命令调优MT7628/MT7615路由器WiFi性能(含参数详解)
  • 最新YOLO实现的舰船检测与识别实时检测平台(Flask+SocketIO+HTML_CSS_JS)
  • SpaceX 拟 600 亿美元收购 Cursor,AI 编码赛道竞争白热化!
  • 2024机器学习新手必备7大免费工具全解析
  • 抖音批量下载工具终极指南:免费高效下载视频、音乐与图集
  • [AutoSar]BSW_OS 05 Autosar OS_ISR 实战:从配置到代码的嵌入式中断设计