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

刷题笔记:力扣第53题-最大子数组和

1.根据题目提示,最快的解法一定是遍历一遍数组、时间复杂度为O(n)的算法。既然只遍历一遍数组,那么就要至少设置三个变量,一个是指向当前元素的指针cur,一个是储存本次计算得出的和数组和curSum,一个是储存目前得出的最大子数组和maxSum。

2.思考:什么情况下需要丢弃前面一段数组呢?可以想到的是,只要前面一段数组和为正数,那么一定是带上前面这段才可能得到最大子数组和;而当前面一段数组和为负数时,丢弃掉前面这段才可能得到得到最大子数组和。那么就需要额外定义一个储存之前数组和的变量preSum。

3.具体的思路为:curSum先初始化为0,用preSum记录上次curSum的值,如果preSum< 0则丢弃掉前面一段数组,让preSum重新初始化为0。每次都计算curSum等于preSum与当前数组元素的和,让maxSum等于过去的maxSum和curSum中的较大值。遍历完整个数组后即可得出最大子数组和。

完整代码如下:

1. // 自定义宏函数,用于比较两个数的大小,返回较大值 2. #define max(a, b) a > b ? a : b 3. 4. int maxSubArray(int* nums, int numsSize) { 5. // 定义变量 6. int cur, // cur:循环计数器,遍历数组的下标 7. preSum, // preSum:之前的累计和(判断是否为负数,决定是否清零) 8. curSum = 0, // curSum:当前连续子数组的累计和 9. maxSum = nums[0]; // maxSum:记录全局最大和(初始化为数组第一个元素,处理全负数情况) 10. 11. // 遍历整个数组 12. for (cur = 0; cur < numsSize; cur++){ 13. // 1. 把上一轮的累计和赋值给 preSum 14. preSum = curSum; 15. 16. // 2. 核心贪心思想: 17. // 如果前面的累计和是负数,那么它只会拖累当前数字,所以直接舍弃前面的,从0开始 18. if (preSum < 0){ 19. preSum = 0; 20. } 21. 22. // 3. 计算以当前数字结尾的最大子数组和 23. curSum = preSum + nums[cur]; 24. 25. // 4. 更新全局最大值:比较历史最大值和当前计算出的和,保留大的 26. maxSum = max(maxSum, curSum); 27. } 28. 29. // 遍历结束,返回最终的最大和 30. return maxSum; 31. }

该算法的本质为贪心算法,时间复杂度为O(n),空间复杂度为O(1),已经是最优解。

4.力扣官方希望解题者尝试一下分治法,简单来说就是“递归切割+合并”。分治法的思路为定义一个结构体存储左端点开始的最大子数组和、右端点开始的最大子数组和,这段区间的最大子数组和以及所有元素的子数组和,之后不断用get函数进行二分,递归分割到子数组只有一个元素后开始合并,算出新的结构体元素值,最后返回合并后的完整数组的最大子数组和即可。

5.代码+解析如下:

1. // 结构体:存储一段区间的4个关键状态 2. struct Status { 3. int lSum; // 从左端点开始的最大子数组和 4. int rSum; // 以右端点结束的最大子数组和 5. int mSum; // 这段区间的【最大子数组和】(最终答案) 6. int iSum; // 这段区间所有元素的总和 7. }; 8. 9. // 核心函数:合并左右两个子区间,计算出新的大区间状态 10. struct Status pushUp(struct Status l, struct Status r) { 11. // 1. 大区间的总和 = 左区间总和 + 右区间总和 12. int iSum = l.iSum + r.iSum; 13. 14. // 2. 新的 lSum:要么是左区间自己的 lSum,要么是左区间全量 + 右区间的 lSum 15. int lSum = fmax(l.lSum, l.iSum + r.lSum); 16. 17. // 3. 新的 rSum:要么是右区间自己的 rSum,要么是右区间全量 + 左区间的 rSum 18. int rSum = fmax(r.rSum, r.iSum + l.rSum); 19. 20. // 4. 新的 mSum(最重要):三种情况取最大值 21. // 情况1:最大子数组在左区间 22. // 情况2:最大子数组在右区间 23. // 情况3:最大子数组跨越中间 24. int mSum = fmax(fmax(l.mSum, r.mSum), l.rSum + r.lSum); 25. 26. // 返回合并后的大区间状态 27. return (struct Status){lSum, rSum, mSum, iSum}; 28. }; 29. 30. // 递归函数:二分求解区间 [l, r] 的 Status 31. struct Status get(int* a, int l, int r) { 32. // 递归终止条件:区间只有一个数字 33. if (l == r) { 34. return (struct Status){a[l], a[l], a[l], a[l]}; 35. } 36. 37. // 二分:将区间从中间分成两半 38. int m = (l + r) >> 1; 39. 40. // 递归求解左半区间 41. struct Status lSub = get(a, l, m); 42. // 递归求解右半区间 43. struct Status rSub = get(a, m + 1, r); 44. 45. // 合并结果并返回 46. return pushUp(lSub, rSub); 47. } 48. 49. // 主函数入口 50. int maxSubArray(int* nums, int numsSize) { 51. // 求解整个数组 [0, numsSize-1] 的 Status,返回 mSum(答案) 52. return get(nums, 0, numsSize - 1).mSum; 53. }

其中fmax函数是C语言数学库自带的函数,作用就是输入两个数,返回较大数,和#define max(a, b) a > b ? a : b作用一样。

6.分治法的时间复杂度为O(nlogn),虽然比贪心算法速度慢,但分治法的递归思想是很重要的,也需要掌握。

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

相关文章:

  • 11-Kotlin高阶特性-协程
  • 天虹购物卡回收小技巧 - 团团收购物卡回收
  • 2026海南GEO优化服务商推荐排名发布:念奴娇稳居榜首,七大服务商精准赋能自贸港企业 - 江湖评测
  • 2026年3月郑州黄金回收店推荐排行榜单:五大机构对比评测与选择指南 - 品牌推荐
  • 收藏!大模型 Agent 项目面试实战:如何讲好 PaiFlow 故事?亮点与难点全解析
  • 激光雷达“线”越多,自动驾驶能力就越强?一场关于感知“像素”的深度辨析
  • 计算机毕业设计springboot在线音乐服务系统 Spring Boot框架下的云端音乐流媒体播放平台开发 基于Java Web技术的智能音乐分享与社区互动系统构建
  • 计算机毕业设计springboot中华汉字学习平台 基于SpringBoot的汉字文化教育传播平台 SpringBoot架构下的传统汉字数字化学习系统
  • 《服务器硬件基础(九)——BIOS/UEFI详解:鲲鹏920关键配置项与测试注意事项》
  • Flutter Beta 版本引入 ScrollCacheExtent ,并修复长久存在的 shrinkWrap NaN 问题
  • 前端-小米商城静态版复刻总结
  • HCIP-AI-EI Developer V2.5 第五、六章笔记
  • GEE案例分析:基于Dynamic World 数据的农用地识别活跃与休耕农田
  • java之抽象类和接口
  • 万爱通礼品卡怎么回收最划算?线上流程分享 - 团团收购物卡回收
  • Python基于卷积神经网络的学情分析系统【附源码、文档说明】
  • 一键生成以假乱真的扫描件!LookScanned:cpolar 内网穿透实验室第 786成功挑战
  • 2026年3月郑州黄金回收店推荐排行榜单:五大机构客观对比与深度评测分析 - 品牌推荐
  • 洛谷:P1554 [USACO06DEC] 梦中的统计 Dream Counting B
  • 博世 HBA 液压制动辅助系统性能规范详解
  • 把杂乱网址装进口袋!Dashlet 轻量仪表盘 : cpolar 内网穿透实验室第 757 个成功挑战
  • 不学 Python,Java 也能调大模型?15 分钟跑通第一个 AI 接口(Java 架构师的 AI 工程笔记 01)
  • Java架构设计:密码加密设计最佳实践(从入门到工业级落地)
  • 什么是原型链(Prototype Chain)?proto和prototype的关系与区别是什么?
  • 【零基础入门】Python机器视觉第五阶段:目标检测实战(YOLOv8)
  • Q312B三菱主基板
  • SpringBoot 配置文件核心用法(Properties YAML)
  • Python 全栈实战 · 第8章
  • 《QGIS快速入门与应用基础》226:添加地图框工具(布局工具栏)
  • 【Vue入门】scoped与组件通信