news 2026/6/15 15:44:46

贪心算法专题(三):负重前行,不如从头再来——「最大子序和」

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
贪心算法专题(三):负重前行,不如从头再来——「最大子序和」

哈喽各位,我是前端小L。

欢迎来到贪心算法专题第三篇! 我们要解决的问题很简单:给你一个整数数组(有正有负),让你找出一个连续的子数组,使得其和最大。

这道题如果用暴力法(两层循环枚举所有子数组),复杂度是 O(N2),会超时。 如果用贪心(或者说动态规划的降维版),复杂度直接降为 O(N)。

力扣 53. 最大子序和

https://leetcode.cn/problems/maximum-subarray/

题目分析:

  • 输入:整数数组nums

  • 目标:找到一个具有最大和的连续子数组。

  • 输出:该子数组的和。

例子:nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]

  • 连续子数组[4, -1, 2, 1]的和是6,是最大的。

核心思维:什么时候该“放弃”?

我们需要一个变量count来记录当前累加的和。 从左向右遍历数组:

  1. 累加count += nums[i]

  2. 贪心决策

    • 如果count变成了负数(比如-2),它对于后面的元素来说,就是一个“累赘”。

    • 因为:负数 + 下一个数 < 下一个数

    • 后面的数会想:“与其加上你这个负数变小,我还不如自己另起炉灶!”

    • 策略:一旦count < 0,立刻把count重置为0(相当于放弃之前的序列,从下一个元素开始重新累加)。

注意:我们需要一个全局变量result来记录我们在过程中遇到的最大值。因为可能整个数组都是负数,或者最大和出现在中间某一段,而不是结尾。

算法流程

  1. 初始化

    • result = INT_MIN(或者nums[0]):记录历史最大值。

    • count = 0:记录当前连续子序列的和。

  2. 遍历数组

    • count += nums[i]

    • 更新最大值if (count > result) result = count。这一步要在重置之前做,确保我们记录下了这一瞬间的高光时刻。

    • 贪心重置if (count < 0) count = 0。如果当前和跌破 0,归零,重新开始。

  3. 返回result

代码实现 (C++)

C++

#include <vector> #include <climits> // for INT_MIN using namespace std; class Solution { public: int maxSubArray(vector<int>& nums) { int result = INT_MIN; // 最终结果 int count = 0; // 当前累加和 for (int i = 0; i < nums.size(); i++) { count += nums[i]; // 1. 累加 // 2. 取最大值 (必须放在重置之前,防止全负数的情况漏掉最大值) if (count > result) { result = count; } // 3. 贪心策略:如果当前和已经是负数了,就扔掉它 if (count < 0) { count = 0; } } return result; } };

深度辨析:贪心 vs 动态规划

这道题其实也是经典的DP题目。

  • DP 定义dp[i]表示以nums[i]结尾的最大连续子数组和。

  • 转移方程dp[i] = max(dp[i-1] + nums[i], nums[i])

    • 如果dp[i-1]是负的,那就不要它了,直接取nums[i]

    • 如果dp[i-1]是正的,那就加上它。

  • 观察:你看,这不就是我们的贪心逻辑吗?count其实就是dp[i-1],当它小于 0 时,我们重置为 0(相当于只取nums[i])。

贪心写法只是把 DP 数组的空间优化到了 O(1) 而已。

深度复杂度分析

  • 时间复杂度:O(N)

    • 只需要遍历一次数组。

  • 空间复杂度:O(1)

    • 只需要两个变量countresult

总结:学会“及时止损”

今天这道题的贪心哲学非常实用:不要因为沉没成本而犹豫。当你发现当前的积累(count)已经变成负资产时,无论之前付出了多少努力(遍历了多少元素),都要果断“归零”,轻装上阵,才能在未来(后面的序列)取得更大的成就(result)。

下一题预告: 如果我们在炒股,这就更刺激了。 假设你能预知未来几天的股价,并且可以无限次地买入卖出(T+0,当天买当天卖都行),你怎么操作才能赚得最多? 贪心策略简直简单到令人发指:只要今天比昨天贵,我就赚这个差价!

下期见!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/15 10:41:06

企业级AI智能体自动化评估:实用指南与最佳实践!

一、AI 智能体评估实用指南 了解如何借助结构化评估框架对企业级 AI 智能体进行评估&#xff0c;涵盖模型测试、产品测试、场景化分析、性能指标及持续监控等方面。 二、AI 智能体评估实用指南 若在部署 AI 智能体时缺乏完善的评估策略&#xff0c;这不仅是技术层面的疏漏&…

作者头像 李华
网站建设 2026/6/15 10:41:05

14、PF 日志、监控、统计及配置优化

PF 日志、监控、统计及配置优化 1. 日志设置与处理 在网络配置中,日志记录是了解系统行为的重要手段。设置 syslogd 来处理数据相对简单,只需选择日志设施、日志级别和操作,然后将相应的行添加到 /etc/syslog.conf 文件中。例如,假设已将系统日志记录器设置为在 log…

作者头像 李华
网站建设 2026/6/15 11:45:35

Dubbo面试必看:同一个服务多个注册如何直连?

文章目录同一个服务多个注册的情况下可以直连某一个服务吗&#xff1f;引言&#xff1a;为什么要关心同一个服务的多个注册&#xff1f;第一部分&#xff1a;同一个服务多个注册的背后逻辑Dubbo 的服务发现机制第二部分&#xff1a;是否可以直接连接某一个服务实例&#xff1f;…

作者头像 李华
网站建设 2026/6/14 7:44:41

Vulkan教程(十九):多帧并行:消除CPU与GPU空闲的核心优化

目录 一、定义并行帧数上限 二、资源多实例化改造 2.1 批量创建命令缓冲 2.2 批量创建同步对象 三、帧索引管理:实现资源循环复用 四、修改渲染循环:实现多帧并行 核心逻辑解析 五、同步方案拓展:时间线信号量 六、总结与后续 当前我们的渲染循环存在一个明显缺陷:…

作者头像 李华
网站建设 2026/6/15 11:47:11

35、脚本开发中的测试、调试与相关特性

脚本开发中的测试、调试与相关特性 1. 脚本测试 在脚本开发中,测试是确保脚本正常运行的重要环节。以文件删除问题为例,直接测试原始代码存在风险,因为其目的是删除文件。为了安全地进行测试,我们可以对代码进行修改: if [[ -d $dir_name ]]; thenif cd $dir_name; th…

作者头像 李华
网站建设 2026/6/15 11:47:21

从ChatBI到自主决策:Agentic BI的演进路径与核心厂商图谱

一、商业智能的新纪元&#xff1a;Agentic BI的崛起近年来&#xff0c;商业智能&#xff08;BI&#xff09;领域正经历一场深刻变革。传统BI工具主要解决“发生了什么”的描述性问题&#xff0c;而新一代的Agentic BI&#xff08;自主智能体商业智能&#xff09;正在向“为什么…

作者头像 李华