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

LeetCode 53.最大子数组和:贪心算法下的连续子数组最优解

一、问题定义与核心挑战

1.1 问题描述

给定一个整数数组 nums,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

1.2 核心特征与难点

  • 子数组连续性:必须是原数组中连续的元素组成(与子序列不同)
  • 存在负数:数组中可能包含负数,增加了选择的复杂性(不能简单累加所有元素)
  • 最优子结构:最大子数组可能存在于数组的任意位置,需要高效定位

示例

  • 输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
  • 输出:6(对应子数组 [4,-1,2,1],和为6)

二、解题思路:贪心算法的局部最优到全局最优

2.1 核心思想

贪心算法的关键在于做出当前状态下的最优选择,并通过局部最优积累全局最优。对于本题:

  • 局部最优:若当前累加和为负数,继续累加会拖累后续子数组的和,因此应重置累加和(从下一个元素重新开始计算)
  • 全局最优:在遍历过程中,始终记录最大的累加和,即为最大子数组和

2.2 直观理解

可以将数组想象成一段起伏的路线,累加和是当前的海拔高度:

  • 当海拔为正时,继续前进可能达到更高海拔(保留当前累加和)
  • 当海拔为负时,继续前进只会更低,不如重新从当前位置出发(重置累加和)
  • 全程记录遇到的最高海拔,即为结果

三、代码逐行解析

3.1 初始化变量

int max = Integer.MIN_VALUE;  // 存储全局最大和,初始化为最小值避免负数场景出错
int cnt = 0;                  // 存储当前子数组的累加和

3.2 遍历数组计算

for (int i = 0; i < nums.length; i++) {cnt += nums[i];  // 累加当前元素到子数组和中// 更新全局最大值:比较当前子数组和与历史最大值max = Math.max(cnt, max);// 贪心决策:若当前累加和为负,重置为0(从下一个元素重新开始)if (cnt <= 0) {cnt = 0;}
}

3.3 返回结果

return max;  // 全局最大子数组和

四、算法执行过程演示

以示例 nums = [-2,1,-3,4,-1,2,1,-5,4] 为例,分步解析:

索引 i当前元素 nums[i]cnt 变化max 变化操作说明
0-20 + (-2) = -2max(-∞, -2) = -2cnt ≤0 → 重置为0
110 + 1 = 1max(-2, 1) = 1cnt 为正 → 保留
2-31 + (-3) = -2max(1, -2) = 1cnt ≤0 → 重置为0
340 + 4 = 4max(1, 4) = 4cnt 为正 → 保留
4-14 + (-1) = 3max(4, 3) = 4cnt 为正 → 保留
523 + 2 = 5max(4, 5) = 5cnt 为正 → 保留
615 + 1 = 6max(5, 6) = 6cnt 为正 → 保留
7-56 + (-5) = 1max(6, 1) = 6cnt 为正 → 保留
841 + 4 = 5max(6, 5) = 6循环结束

最终结果为 6,与预期一致。

五、核心逻辑深度解析

5.1 为什么重置累加和?

cnt ≤ 0 时,说明当前子数组的和已经是负数或零,继续带着这个和计算后续元素:

  • 若后续元素为正数,加上负数会比直接从该正数开始计算更小
  • 若后续元素为负数,加上负数会变得更小
  • 因此重置为0(相当于从下一个元素重新开始计算子数组和)是局部最优选择

5.2 为什么不需要记录子数组的起止位置?

题目只要求返回最大和,无需知道具体子数组的位置,因此只需通过 max 变量跟踪最大值即可,节省空间。

5.3 全负数场景的处理

当数组全为负数时(如 [-3, -1, -2]):

  • 每次累加后 cnt 都是负数,会被重置
  • max 会在每次累加后更新,最终保留最大的那个负数(即数组中最大的元素)
  • 符合“子数组最少包含一个元素”的要求

六、算法复杂度分析

  • 时间复杂度O(n),仅需遍历数组一次(n 为数组长度)
  • 空间复杂度O(1),仅使用常数个变量(maxcnt),与输入规模无关

七、常见误区与优化说明

7.1 误区1:初始值设置错误

若将 max 初始化为0,当数组全为负数时,会错误返回0(正确结果应为最大的负数)。因此必须初始化为 Integer.MIN_VALUE

7.2 误区2:重置条件判断错误

若将重置条件设为 cnt < 0(而非 cnt ≤ 0),当 cnt = 0 时不会重置,可能导致后续计算包含无意义的0(如数组 [0, -1] 会得到0,虽然结果正确,但逻辑不够严谨)。

7.3 与动态规划的关联

本题也可用动态规划求解(dp[i] = max(nums[i], dp[i-1] + nums[i])),但贪心算法更简洁,空间效率更高(动态规划若不优化空间为 O(n))。两种算法本质都是判断“是否保留之前的累加和”。

八、总结:贪心算法的适用场景

本题的贪心解法体现了“局部最优推导全局最优”的核心思想,适用于以下场景:

  • 问题可分解为一系列局部决策
  • 每个局部决策的最优选择能累积成全局最优
  • 无需回溯(每个决策一旦做出就不再修改)

最大子数组和问题通过简单的累加、比较、重置操作,在 linear 时间内解决,是贪心算法高效性的典型体现。掌握这种思路,可解决类似的连续序列优化问题(如最大乘积子数组等)。

http://www.dtcms.com/a/333100.html

相关文章:

  • Android项目中Ktor的引入与使用实践
  • mlir clone
  • 【C#补全计划】事件
  • 【C#】 GridControl与GridView、容器和视图
  • Spring事务 概念 配置 隔离级别 脏读幻读不可重复读 传播行为
  • pyinstaller-从安装到高级使用
  • align-content 设置侧轴上的子元素的排列方式(多行)
  • Git代码版本管理
  • OpenCV---getStructuringElement 结构元素获取
  • 设计心得——如何架构选型
  • ffmpeg 安装、配置与使用完全指南
  • 自学大语言模型之Transformer的Tokenizer
  • jenkins 自动部署
  • 开发Chrome/Edge插件基本流程
  • mysql中in 和 exists 区别
  • 从传感器到大模型:Jetson Thor + LLM.VLA + Holoscan 的边缘推理全链路实战
  • 基于改进Apriori算法的Web文档聚类方法研究(一)
  • 20250815给ubuntu22.04.5的系统缩小/home分区
  • Doris FE 应急恢复手册:六大经典故障场景与解决方案
  • WITRAN:基于改进的RNN时间序列预测模型
  • rent8 安装部署教程之 Windows
  • Effective C++ 条款43:学习处理模板化基类内的名称
  • 俄罗斯信封套娃问题-二维最长递增子序列
  • 【JavaEE】多线程 -- 线程安全
  • UI-TARS-Desktop 深度解析:下一代智能自动化桌面平台
  • Stagehand深度解析:从开源自动化工具到企业级RPA平台的演进之路
  • 神经网络 小土堆pytorch记录
  • nVidia Tesla P40使用anaconda本地重编译pytorch3d成功加载ComfyUI-3D-Pack
  • 基于多分类的工业异常声检测及应用
  • 微信小程序 拖拽签章