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

剑指offer-73、连续⼦数组的最⼤和(⼆)

题⽬描述

输⼊⼀个⻓度为n 的整型数组array ,数组中的⼀个或连续多个整数组成⼀个⼦数组,找到⼀个具有
最⼤和的连续⼦数组。

  1. ⼦数组是连续的,⽐如[1,3,5,7,9] 的⼦数组有[1,3] , [3,5,7] 等等,但是[1,3,7] 不是⼦数组
  2. 如果存在多个最⼤和的连续⼦数组,那么返回其中⻓度最⻓的,该题数据保证这个最⻓的只存在⼀个
  3. 该题定义的⼦数组的最⼩⻓度为1 ,不存在为空的⼦数组,即不存在[]是某个数组的⼦数组
  4. 返回的数组不计⼊空间复杂度计算

示例 1
输⼊:[1,-2,3,10,-4,7,2,-5]
返回值:[3,10,-4,7,2]
说明:经分析可知,输⼊数组的⼦数组[3,10,-4,7,2]可以求得最⼤和为18,故返回[3,10,-4,7,2]

示例 2
输⼊:[1]
返回值:[1]

思路及解答

暴力枚举

通过三重循环枚举所有可能的子数组,使用三重循环枚举所有可能的子数组起始和结束位置,计算每个子数组的和

public class Solution {public int[] findMaxSubarray(int[] array) {if (array == null || array.length == 0) {return new int[0];}int n = array.length;int maxSum = Integer.MIN_VALUE;int start = 0, end = 0;// 第一重循环:子数组起始位置for (int i = 0; i < n; i++) {// 第二重循环:子数组结束位置for (int j = i; j < n; j++) {int currentSum = 0;// 第三重循环:计算子数组和for (int k = i; k <= j; k++) {currentSum += array[k];}// 更新最大和及位置(优先选择长度更长的)if (currentSum > maxSum || (currentSum == maxSum && (j - i) > (end - start))) {maxSum = currentSum;start = i;end = j;}}}// 构建结果数组int[] result = new int[end - start + 1];System.arraycopy(array, start, result, 0, result.length);return result;}
}
  • 时间复杂度:O(n³),三重循环嵌套
  • 空间复杂度:O(1),除结果外只使用常数空间

优化枚举法(前缀和思想)

在暴力法基础上优化,利用前缀和在计算子数组和时复用之前的结果,减少一层循环

public class Solution {public int[] findMaxSubarray(int[] array) {if (array == null || array.length == 0) {return new int[0];}int n = array.length;int maxSum = Integer.MIN_VALUE;int start = 0, end = 0;// 外层循环:子数组起始位置for (int i = 0; i < n; i++) {int currentSum = 0;// 内层循环:从起始位置向后累加for (int j = i; j < n; j++) {currentSum += array[j]; // 复用之前计算的结果// 更新最大和(优先选择长度更长的)if (currentSum > maxSum || (currentSum == maxSum && (j - i) > (end - start))) {maxSum = currentSum;start = i;end = j;}}}return buildResult(array, start, end);}private int[] buildResult(int[] array, int start, int end) {int[] result = new int[end - start + 1];System.arraycopy(array, start, result, 0, result.length);return result;}
}
  • 时间复杂度:O(n²),减少了一层循环
  • 空间复杂度:O(1),常数级别空间复杂度

分治法(递归思维)

采用分治思想,将问题分解为更小的子问题

将问题分解为左半部分、右半部分和跨越中间的三部分

即递归求解左右子数组,合并时处理跨越中间的情况

public class Solution {public int[] findMaxSubarray(int[] array) {if (array == null || array.length == 0) {return new int[0];}Result result = findMaxSubarrayHelper(array, 0, array.length - 1);return buildResult(array, result.start, result.end);}private Result findMaxSubarrayHelper(int[] array, int left, int right) {// 基准情况:单个元素if (left == right) {return new Result(left, right, array[left]);}int mid = left + (right - left) / 2;// 递归求解左右两部分Result leftResult = findMaxSubarrayHelper(array, left, mid);Result rightResult = findMaxSubarrayHelper(array, mid + 1, right);Result crossResult = findMaxCrossingSubarray(array, left, mid, right);// 返回三者中的最大值(长度优先)return getMaxResult(leftResult, rightResult, crossResult);}private Result findMaxCrossingSubarray(int[] array, int left, int mid, int right) {// 向左扩展找最大和int leftSum = Integer.MIN_VALUE;int sum = 0;int maxLeft = mid;for (int i = mid; i >= left; i--) {sum += array[i];if (sum > leftSum) {leftSum = sum;maxLeft = i;}}// 向右扩展找最大和int rightSum = Integer.MIN_VALUE;sum = 0;int maxRight = mid + 1;for (int i = mid + 1; i <= right; i++) {sum += array[i];if (sum > rightSum) {rightSum = sum;maxRight = i;}}return new Result(maxLeft, maxRight, leftSum + rightSum);}private Result getMaxResult(Result r1, Result r2, Result r3) {Result maxResult = r1;if (r2.sum > maxResult.sum || (r2.sum == maxResult.sum && (r2.end - r2.start) > (maxResult.end - maxResult.start))) {maxResult = r2;}if (r3.sum > maxResult.sum || (r3.sum == maxResult.sum && (r3.end - r3.start) > (maxResult.end - maxResult.start))) {maxResult = r3;}return maxResult;}private int[] buildResult(int[] array, int start, int end) {int[] result = new int[end - start + 1];System.arraycopy(array, start, result, 0, result.length);return result;}// 辅助类存储子数组结果class Result {int start, end, sum;Result(int s, int e, int sum) {this.start = s;this.end = e;this.sum = sum;}}
}
  • 时间复杂度:O(n log n),递归深度为log n,每层处理时间为O(n)
  • 空间复杂度:O(log n),递归调用栈的深度

动态规划-Kadane算法(最优解)

遍历数组,维护当前子数组和,根据规则重置或扩展当前子数组

假设现在有 n 个元素,突然加上⼀个元素,变成 n+1 个元素,对连续⼦数组的最⼤和有什么影响呢?

我们只需要知道以每⼀个元素结尾的最⼤连续⼦数组,再维护⼀个最⼤的值即可。

假设数组为num[] ,⽤ dp[i] 表示以下标 i 为终点的最⼤连续⼦数组和,遍历每⼀个新的元素nums[i+1] ,以 num[i+1] 为连续⼦数组的情况只有两种:

  • dp[i] + num[i+1]
  • 只有num[i+1]

所以以nums[n] 结尾的最⼤连续⼦数组和为: dp[i] = max( dp[i-1] + num[i], num[i])

在计算的过程中,需要维护⼀个最⼤的值,并且把该连续⼦数组的左边界以及右边界维护好,最后根据维护的区间返回。

public class Solution85 {public int[] FindGreatestSumOfSubArray(int[] array) {int[] dp = new int[array.length];dp[0] = array[0];int maxsum = dp[0];int left = 0, right = 0;int maxLeft = 0, maxRight = 0;for (int i = 1; i < array.length; i++) {right++;dp[i] = Math.max(dp[i - 1] + array[i], array[i]);if (dp[i - 1] + array[i] < array[i]) {left = right;}// 更新最⼤值以及更新最⼤和的⼦数组的边界if (dp[i] > maxsum || dp[i] == maxsum && (right - left + 1) > (maxRight - maxLeft + 1)) {maxsum = dp[i];maxLeft = left;maxRight = right;}}// 保存结果int[] res = new int[maxRight - maxLeft + 1];for (int i = maxLeft, j = 0; i <= maxRight; i++, j++) {res[j] = array[i];}return res;}
}
  • 时间复杂度:O(n),单次遍历数组
  • 空间复杂度:O(1),只使用常数变量
http://www.jsqmd.com/news/344391/

相关文章:

  • 答辩前一晚,最值得做的 5 件事
  • 【白血病检测】数字图像处理白血病检测【含GUI Matlab源码 15071期】含报告
  • 66 Spring线程池配置
  • 信息系统仿真:数据传输与网络仿真_(4).仿真工具与技术
  • 68 @Async异步注解深度实践
  • 【5G通信】5G NR-PRS赋能6G多基地ISAC:LoSNLoS混合场景定位【含Matlab源码 15067期】复现含文献
  • JVM 性能调优流程实战:从开发规范到生产应急排查
  • AI大模型应用开发工程师全解析:月薪60k+的桥梁职业指南
  • 信息系统仿真:数据传输与网络仿真_(5).数据编码与解码
  • 世界模型:大模型智能体的‘内部引擎‘,AI理解世界的核心
  • 【图像加密解密】融合超混沌系统和DNA编码彩色图像加密解密(含图像分析)【含Matlab源码 15046期】
  • 信息系统仿真:数据传输与网络仿真_(2).数据传输基础
  • 【图像压缩】小波变换图像编码技术图像压缩(含峰值信噪比和压缩比来确定编码器的性能)【含Matlab源码 15049期】
  • 基于Ai Coding,20天完成一个基于大模型的医学分析系统:Ai体征分析助手
  • 收藏这份大模型应用开发路线图:零基础也能成为AI应用开发者_大模型应用开发学习路线
  • 从0到1构建个人智能助手Agent:6步实战路线图,避开90%项目踩的坑
  • 基于python大数据的房价数据分析强大的系统
  • 慕尼黑工大高级深度学习机器视觉笔记-全-
  • Capacitor:跨平台Web原生应用开发利器,现已全面适配鸿蒙
  • PaperPass
  • 纽约大学地理深度学习笔记-全-
  • Python 字典演进史:从无序到有序的优雅蜕变与实战应用
  • Agentic AI核心认知闭环:感知-规划-行动-反思,让AI越用越聪明
  • 从零开始搭建你的私有手绘白板:Excalidraw部署实战指南
  • 主流质检相机选型对比(电子/五金/汽车产线)
  • 掌握大模型核心技术:从RAG到Agent架构,一文读懂AI技术发展脉络【建议收藏】
  • 电子配件流水线扫码+PLC联动上位机实战:C#完整落地方案
  • 程序员大模型转型指南:从基础到微调的完整学习路径!转AI大模型开发学习顺序真的很重要!!
  • 多线程调试技巧(C# / .NET 上位机开发专用)
  • 2026 年最值得使用的 7 款 PHP 管理后台框架推荐