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

动态规划法 - 53. 最大子数组和

什么是动态规划法?

简单说,动态规划(Dynamic Programming,简称 DP) 是一种**「把复杂问题拆解成小问题,通过解决小问题来解决大问题」**的方法。
核心思路有两个:
1.拆分问题:把原问题拆成多个相似的「子问题」(比如求 “整个数组的最大子数组和” 可以拆 成 “以每个元素结尾的最大子数组和”)。
2.记住答案:用一个表格(或变量)记录子问题的答案,避免重复计算(这一步叫「记忆化」)。

用动态规划解决 “最大子数组和” 的标准思路

以 nums = [-2, 1, -3, 4] 为例:
1.定义子问题:设 dp[i] 为「以第 i 个元素结尾的最大子数组和」。

  • 比如 dp[0] 是 “以 -2 结尾的最大和” → 只能是 -2。
  • dp[1] 是 “以 1 结尾的最大和” → 要么单独用 1,要么用 dp[0] + 1(即 -2 + 1 = -1),取大的那个 → 1。

2.找规律(状态转移方程):dp[i] = max(nums[i], dp[i-1] + nums[i])(要么从当前元素重新开始,要么接上前面的子数组)
3.计算所有子问题:

  • dp[0] = -2
  • dp[1] = max(1, -2+1) = 1
  • dp[2] = max(-3, 1-3) = -2
  • dp[3] = max(4, -2+4) = 4

4.求最终答案:所有 dp[i] 中的最大值 → 4。
我们现在用的方法,其实是动态规划的 “升级版”
上面的标准思路需要一个 dp 数组来存所有子问题的答案(空间复杂度 O(n)),但我们可以优化:
观察发现:计算 dp[i] 只需要前一个 dp[i-1] 的值,不需要整个数组。
所以可以用一个变量 sum 代替 dp 数组(sum 就代表当前的 dp[i]),这样空间复杂度就降到了 O(1)。
这就是我们现在用的方法:

  • sum 等价于 dp[i](当前子问题的答案)。
  • sum = max(nums[i], sum + nums[i]) 就是状态转移方程。
  • res 用来记录所有 sum 中的最大值(即最终答案)。

总结

  • 标准动态规划:用数组存所有子问题答案,思路直观,空间稍大。
  • 我们现在的方法:用单个变量代替数组,核心逻辑不变,是动态规划的「空间优化版」。

题目

https://leetcode.cn/problems/maximum-subarray/description/?envType=study-plan-v2&envId=top-100-liked

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 子数组是数组中的一个连续部分。
示例 1: 输入:nums = [-2,1,-3,4,-1,2,1,-5,4]输出:6解释:连续子数组 [4,-1,2,1] 的和最大,为
6 。 示例 2: 输入:nums = [1]输出:1 示例 3: 输入:nums = [5,4,-1,7,8]输出:23

题解

class Solution {public int maxSubArray(int[] nums) {// 把sum初始化为数组第一个元素int sum = nums[0];// 结果也初始化为第一个元素(因为最大和至少是它自己)int res = nums[0];// 从第二个元素开始遍历(索引1)for (int i = 1; i < nums.length; i++) {// 同样先判断:之前的sum是否有用if (sum > 0) {// 有用就累加当前元素sum += nums[i];} else {// 没用就从当前元素重新开始sum = nums[i];}// 更新最大和res = Math.max(res, sum);}return res;}
}

过程解读(结合 “攒钱” 例子)

  • 初始状态:手里先拿着第一天的钱 sum=-1(亏了 1 块),历史最多钱 res=-1。
  • 第二天(元素 2):之前手里是亏的(sum=-1),不如直接拿今天的 2 块,sum 变成 2。历史最多钱更新为 2。
  • 第三天(元素 - 3):手里有 2 块(正数),虽然今天花了 3 块,但还是加上试试,sum=2-3=-1。历史最多钱还是 2(因为 - 1 < 2)。
  • 第四天(元素 4):手里是 - 1(亏的),直接拿今天的 4 块,sum 变成 4。历史最多钱更新为 4。
  • 第五天(元素 - 1):手里有 4 块(正数),今天花 1 块,加上后 sum=4-1=3。历史最多钱还是 4(因为 3 < 4)。
    最终结果是 4,对应最大子数组 [4](或者理解为 “只拿第四天的钱最划算”)。
http://www.dtcms.com/a/336207.html

相关文章:

  • MySQL数据库基础操作指南:从创建到管理的完整流程
  • Linux系统中6种替代top的工具
  • SparkSQL性能优化实践指南
  • ubuntu 24.04 安装
  • RAC环境redo在各节点本地导致数据库故障恢复---惜分飞
  • 云智智慧停充一体云-allnew全新体验-路内停车源码+路外停车源码+充电桩源码解决方案
  • 从零配置YOLOv8环境:RTX 3060显卡完整指南
  • 43.安卓逆向2-补环境-使用unidbg(使用Smali语法调用方法和使用方法地址调用方法)
  • n2n局域网搭建
  • 0-12岁幼儿启蒙与教育
  • Linux操作系统远程连接
  • 代码管理系统简介与部署
  • 《告别 if-else 迷宫:Python 策略模式 (Strategy Pattern) 的优雅之道》
  • Honor of Kings 101star (S40) 2025.08.17
  • Spring Bean 的生命周期:从创建到销毁的完整旅程​
  • Gemini 学习记录:实践与反思
  • 深度解析 Spring Bean 生命周期
  • UE5多人MOBA+GAS 49、创建大厅
  • MariaDB 多源复制
  • Qt异步编程:QFuture与QPromise深度解析
  • Mysql常见的查询总结
  • Golang database/sql 包深度解析(二):连接池实现原理
  • 快速掌握Hardhat与Solidity智能合约开发
  • Rust Web 全栈开发(十三):发布
  • 实时视频延迟优化实战:RTSP与RTMP播放器哪个延迟更低?
  • 数据结构初阶(19)外排序·文件归并排序的实现
  • 博士招生 | 麻省理工学院 招收化学+人工智能方向 博士/博士后
  • 【编程实践】关于S3DIS数据集的问题
  • Docker+飞算JavaAI=未来:全流程容器化AI开发实战
  • Python注解