尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

剑指offer-30、连续⼦数组的最⼤和

剑指offer-30、连续⼦数组的最⼤和
📅 发布时间:2026/6/20 17:14:14

题⽬描述

输⼊⼀个整型数组,数组⾥有正数也有负数。数组中的⼀个或连续多个整数组成⼀个⼦数组。求所有⼦数组的和的最⼤值。要求时间复杂度为 O(n) .

示例1

输⼊:[1,-2,3,10,-4,7,2,-5]

返回值:18

输⼊的数组为 {1,-2,3,10,-4,7,2,-5} ,和最⼤的⼦数组为 {3,10,-4,7,2} ,因此输出为该⼦数组的和 18 。

思路及解答

暴⼒破解

通过两层循环枚举所有可能的子数组起点和终点,计算每个子数组的和并记录最大值。

public class Solution {public int maxSubArray(int[] nums) {int n = nums.length;int maxSum = Integer.MIN_VALUE; // 初始化为最小整数,以处理全负数数组for (int i = 0; i < n; i++) {int currentSum = 0; // 记录从i开始到j的子数组和for (int j = i; j < n; j++) {currentSum += nums[j]; // 累加当前元素if (currentSum > maxSum) {maxSum = currentSum; // 更新全局最大和}}}return maxSum;}
}
  • 时间复杂度​:O(n²),因为有两层嵌套循环。
  • ​空间复杂度​:O(1),只使用了常数级别的额外空间。

分治法

分治法将数组分成左右两半,分别递归求解左右半边的最大子数组和,再计算跨越中点的最大子数组和,最后合并结果。

public class Solution {public int maxSubArray(int[] nums) {return divideAndConquer(nums, 0, nums.length - 1);}private int divideAndConquer(int[] nums, int left, int right) {if (left == right) {return nums[left]; // 递归基:只有一个元素}int mid = left + (right - left) / 2;int leftMax = divideAndConquer(nums, left, mid); // 左半部分的最大子数组和int rightMax = divideAndConquer(nums, mid + 1, right); // 右半部分的最大子数组和int crossMax = maxCrossingSum(nums, left, mid, right); // 跨越中点的最大子数组和return Math.max(Math.max(leftMax, rightMax), crossMax); // 返回三者中的最大值}private int maxCrossingSum(int[] nums, int left, int mid, int right) {int leftSum = Integer.MIN_VALUE;int sum = 0;for (int i = mid; i >= left; i--) { // 从中点向左扫描sum += nums[i];if (sum > leftSum) {leftSum = sum;}}int rightSum = Integer.MIN_VALUE;sum = 0;for (int i = mid + 1; i <= right; i++) { // 从中点向右扫描sum += nums[i];if (sum > rightSum) {rightSum = sum;}}return leftSum + rightSum; // 合并左右两部分的和}
}
  • ​时间复杂度​:O(n log n),由递归树深度(log n)和每层合并操作(n)决定。
  • ​空间复杂度​:O(log n),递归调用栈的深度。

动态规划

⾸先我们定义这个问题:

dp[i] 表示下标以i结尾的连续⼦数组的最⼤和,假设数组⼤⼩为 n ,那么最终求解的就是 dp[n-1] 。

下标以 i 结尾的连续⼦数组的最⼤和,怎么求呢?

要想求 dp[i] ,那我们现在假设⼀下,假设下标以i-1 结尾的连续⼦数组的最⼤和为 dp[i-1] ,数组第 i 个元素是 nums[i] ,那么当前的连续⼦数组的最⼤和,要么是前⾯的加上当前的元素: dp[i-1]+nums[i] ,要么是舍弃掉之前的 dp[i-1](这个很可能是负数) ,取现在的 nums[i] ;

因此,状态转移⽅程为:dp[i] = max{dp[i-1]+nums[i] , nums[i]}

但是,值得注意的是, Max{dp[i-1]+nums[i],nums[i]} 求得的仅仅是以 i 下标结尾的⼦数组的最⼤和,之前计算的连续⼦数组最⼤和需要保存起来,不断的和当前计算的最⼤和⽐较,取最⼤值。

public int FindGreatestSumOfSubArray(int[] array) {int res = array[0]; //记录当前所有⼦数组的和的最⼤值int[] dp = new int[array.length]; dp[0] = array[0]; for (int i = 1; i < array.length; i++) {dp[i] = Math.max(dp[i-1] + array[i], array[i]);res = Math.max(max, res);}return res;
}
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

这里只用到了dp[i]和dp[i-1],显然还可以再优化。即

public int FindGreatestSumOfSubArray(int[] array) {int res = array[0]; //记录当前所有⼦数组的和的最⼤值int max = array[0]; //包含array[i]的连续数组最⼤值for (int i = 1; i < array.length; i++) {max = Math.max(max + array[i], array[i]);res = Math.max(max, res);}return res;
}
  • 时间复杂度:O(n)
  • 空间复杂度:O(1),只使用了两个变量。

本文来自在线网站:seven的菜鸟成长之路,作者:seven,转载请注明原文链接:www.seven97.top

相关新闻

  • 小区物业的智慧:轻松图解JVM垃圾回收的奥秘
  • CUDA多版本安装切换(转链接自用)
  • 权变与权力异化,是斗争的根源,超越自我,良性循环

最新新闻

  • 免费开源桌面分区神器:3步打造整洁高效的Windows工作空间
  • 告别论文焦虑:6款2026年优质AI论文平台深度横评
  • DeepSeek-V4-Flash与V4-Pro技术解析:国产大模型私有化部署新基准
  • Playwright自动化测试四大实战技巧:从MCP思想到工程实践
  • 2026年6月最新雷达中国官方售后电话热线客服地址服务网点 - 亨得利官方服务中心
  • 武汉助产学校:职教升学理想坐标,护理人才培育摇篮 - 辛云教育资讯

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号