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

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.xdnf.cn/news/17817.html

相关文章:

  • 【测试用例】
  • STM32 - Embedded IDE - GCC - 解决LWRB库在GCC编译器会编译失败,在ARMCC编译器时却正常编译
  • 肖臻《区块链技术与应用》第16讲 - 以太坊的“世界状态”:从哈希表到MPT架构演进
  • 安装openmmlab时出错
  • IStoreOS(OpenWrt)开启IPV6
  • LeetCode 刷题【42. 接雨水】
  • 大规模Go网络应用的部署与监控实战指南
  • python30-正则表达式
  • 应急救援智能接处警系统——科技赋能应急,筑牢安全防线
  • 线程P5 | 单例模式[线程安全版]~懒汉 + 饿汉
  • 从0开始学习Java+AI知识点总结-15.后端web基础(Maven基础)
  • UI-TARS-Desktop 产品发展史:从实验室原型到企业级解决方案
  • 流处理、实时分析与RAG驱动的Python ETL框架:构建智能数据管道(中)
  • python中的map函数
  • Android UI(一)登录注册 - Compose
  • 【数据可视化-89】基孔肯雅热病例数据分析与可视化:Python + pyecharts洞察疫情动态
  • RH134 管理基本存储知识点
  • 【C#补全计划】泛型约束
  • OpenCv(二)——边界填充、阈值处理
  • 37 C++ STL模板库6-string_view
  • Mybatis实现页面增删改查
  • 解锁AI潜能:五步写出让大模型神级指令
  • C#面试题及详细答案120道(01-10)-- 基础语法与数据类型
  • 《嵌入式 C 语言编码规范个人笔记》参考华为C语言规范标准
  • 机器学习-支持向量机器(SVM)
  • CPP模板编程
  • Python学习-----3.基础语法(2)
  • 广义矩估计随机近似中1.2和2.1的差异
  • 如何手动开启 Hyper-V?Windows 10/11 详细开启教程
  • Mybatis 源码解读-Plugin插件源码