news 2026/7/2 1:42:35

算法题 环形子数组的最大和

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
算法题 环形子数组的最大和

918. 环形子数组的最大和

问题描述

给定一个环形整数数组nums(即数组的末端将会与开头相连),返回非空子数组的最大可能和。

注意:环形数组意味着数组可以首尾相连,因此子数组可以跨越数组的末尾和开头。

示例

输入: nums = [1,-2,3,-2] 输出: 3 解释: 子数组 [3] 的和最大。 输入: nums = [5,-3,5] 输出: 10 解释: 子数组 [5,5] 的和最大(跨越末尾和开头)。 输入: nums = [-3,-2,-3] 输出: -2 解释: 子数组 [-2] 的和最大。

算法思路

两种情况

  1. 非环形情况:最大子数组完全在数组内部,不跨越边界

    • 使用经典的 Kadane 算法
  2. 环形情况:最大子数组跨越数组末尾和开头

    • 等价于总和减去最小子数组的和
    • 跨越边界的子数组 = 整个数组 - 中间的最小子数组

代码实现

方法一:Kadane算法

classSolution{/** * 计算环形数组中非空子数组的最大和 * * @param nums 环形整数数组 * @return 非空子数组的最大可能和 */publicintmaxSubarraySumCircular(int[]nums){// 使用Kadane算法计算最大子数组和intmaxSum=kadaneMax(nums);// 计算数组总和inttotalSum=0;for(intnum:nums){totalSum+=num;}// 使用Kadane算法计算最小子数组和intminSum=kadaneMin(nums);// 特殊情况:如果所有元素都是负数,minSum == totalSum// 此时环形情况会得到 totalSum - minSum = 0,需要非空子数组// 所以直接返回 maxSum(即最大的单个元素)if(totalSum==minSum){returnmaxSum;}// 返回非环形情况和环形情况的最大值returnMath.max(maxSum,totalSum-minSum);}/** * Kadane算法:计算最大子数组和 */privateintkadaneMax(int[]nums){intmaxSoFar=nums[0];intmaxEndingHere=nums[0];for(inti=1;i<nums.length;i++){// 要么扩展之前的子数组,要么重新开始maxEndingHere=Math.max(nums[i],maxEndingHere+nums[i]);maxSoFar=Math.max(maxSoFar,maxEndingHere);}returnmaxSoFar;}/** * Kadane算法变种:计算最小子数组和 */privateintkadaneMin(int[]nums){intminSoFar=nums[0];intminEndingHere=nums[0];for(inti=1;i<nums.length;i++){// 要么扩展之前的子数组,要么重新开始minEndingHere=Math.min(nums[i],minEndingHere+nums[i]);minSoFar=Math.min(minSoFar,minEndingHere);}returnminSoFar;}}

方法二:一次遍历

classSolution{/** * 一次遍历计算最大子数组和、最小子数组和和总和 * * @param nums 环形整数数组 * @return 非空子数组的最大可能和 */publicintmaxSubarraySumCircular(int[]nums){intmaxSum=nums[0];// 最大子数组和intminSum=nums[0];// 最小子数组和intmaxEndingHere=nums[0];// 当前最大子数组和intminEndingHere=nums[0];// 当前最小子数组和inttotalSum=nums[0];// 数组总和for(inti=1;i<nums.length;i++){intnum=nums[i];totalSum+=num;// 更新最大子数组和maxEndingHere=Math.max(num,maxEndingHere+num);maxSum=Math.max(maxSum,maxEndingHere);// 更新最小子数组和minEndingHere=Math.min(num,minEndingHere+num);minSum=Math.min(minSum,minEndingHere);}// 特殊情况处理:所有元素都是负数if(totalSum==minSum){returnmaxSum;}returnMath.max(maxSum,totalSum-minSum);}}

算法分析

  • 时间复杂度:O(n)
    • 只需要遍历数组一次或两次
  • 空间复杂度:O(1)
    • 只使用常数个额外变量

算法过程

输入:nums = [5,-3,5]

  1. 计算非环形最大子数组和:

    • [5] = 5,[5,-3] = 2,[5,-3,5] = 7,[-3] = -3,[-3,5] = 2,[5] = 5
    • 最大值 = 7
  2. 计算总和:5 + (-3) + 5 = 7

  3. 计算最小子数组和:

    • 最小子数组是[-3],和为-3
  4. 环形最大子数组和 =总和 - 最小子数组和 = 7 - (-3) = 10

  5. 最终答案 =max(7, 10) = 10

输入:nums = [-3,-2,-3]

  1. 非环形最大子数组和 =-2
  2. 总和 =-8
  3. 最小子数组和 =-8(整个数组)
  4. 由于总和 == 最小子数组和,返回非环形结果-2

测试用例

publicstaticvoidmain(String[]args){Solutionsolution=newSolution();// 测试用例1:标准示例int[]nums1={1,-2,3,-2};System.out.println("Test 1: "+solution.maxSubarraySumCircular(nums1));// 3// 测试用例2:环形情况更优int[]nums2={5,-3,5};System.out.println("Test 2: "+solution.maxSubarraySumCircular(nums2));// 10// 测试用例3:全负数int[]nums3={-3,-2,-3};System.out.println("Test 3: "+solution.maxSubarraySumCircular(nums3));// -2// 测试用例4:全正数int[]nums4={1,2,3,4};System.out.println("Test 4: "+solution.maxSubarraySumCircular(nums4));// 10// 测试用例5:单元素int[]nums5={5};System.out.println("Test 5: "+solution.maxSubarraySumCircular(nums5));// 5// 测试用例6:两元素int[]nums6={-2,-3};System.out.println("Test 6: "+solution.maxSubarraySumCircular(nums6));// -2// 测试用例7:复杂环形情况int[]nums7={3,-1,2,-1};System.out.println("Test 7: "+solution.maxSubarraySumCircular(nums7));// 4// 非环形:[3,-1,2] = 4,环形:[2,-1,3] = 4// 测试用例8:另一个复杂情况int[]nums8={3,-2,2,-3};System.out.println("Test 8: "+solution.maxSubarraySumCircular(nums8));// 3// 非环形:[3] = 3,环形:[2,-3,3] = 2// 测试用例9:大数值int[]nums9={10000,-10000,10000};System.out.println("Test 9: "+solution.maxSubarraySumCircular(nums9));// 20000// 测试用例10:交替正负int[]nums10={1,-1,1,-1,1};System.out.println("Test 10: "+solution.maxSubarraySumCircular(nums10));// 3// 环形:[1,-1,1,-1,1] 全部 = 1,或者 [1,1,1] 跨越 = 3}

关键点

  1. 两种情况

    • 非环形:标准的最大子数组问题
    • 环形:相当于找最小子数组,然后用总和减去它
  2. 特殊情况处理

    • 当所有元素都是负数时,最小子数组就是整个数组
  3. Kadane算法

    • 不仅可以求最大子数组,也可以求最小子数组
    • 核心思想是动态规划:每个位置要么开始新的子数组,要么扩展之前的子数组
  4. 数学

    • 环形最大子数组 + 中间最小子数组 = 整个数组
    • 环形最大子数组 = 总和 - 最小子数组

常见问题

  1. 为什么不能直接用环形情况?
    • 当所有元素都是负数时,环形情况会错误地返回0
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/1 19:02:06

边缘计算网关有什么好用的推荐

随着工业4.0与物联网技术的深度融合&#xff0c;数据采集的实时性、安全性以及本地处理需求愈发凸显&#xff0c;边缘计算网关作为连接物理设备与云端平台的核心枢纽&#xff0c;成为破解数据传输延迟、带宽占用过高难题的关键设备。如今市场上边缘计算网关品牌众多&#xff0c…

作者头像 李华
网站建设 2026/6/30 0:37:16

计算机毕业设计 | SpringBoot+vue社团管理系统 大学社团招新(附源码+论文)

1&#xff0c;绪论 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理社团管理系统的相关信息成为必然…

作者头像 李华
网站建设 2026/6/30 15:38:29

MiDaS模型优化:提升小物体深度估计精度的方法

MiDaS模型优化&#xff1a;提升小物体深度估计精度的方法 1. 引言&#xff1a;AI 单目深度估计的挑战与机遇 随着计算机视觉技术的发展&#xff0c;单目深度估计&#xff08;Monocular Depth Estimation&#xff09;逐渐成为3D感知领域的重要研究方向。相比双目或LiDAR等硬件…

作者头像 李华
网站建设 2026/6/26 17:35:43

视觉代理能力全解析|通过Qwen3-VL-WEBUI实现GUI自动操作

视觉代理能力全解析&#xff5c;通过Qwen3-VL-WEBUI实现GUI自动操作 在某智能运维平台的测试环境中&#xff0c;一张Windows系统蓝屏截图刚上传&#xff0c;不到5秒后系统返回了结构化诊断报告&#xff1a;“检测到IRQL_NOT_LESS_OR_EQUAL错误码&#xff0c;建议检查第三方驱动…

作者头像 李华
网站建设 2026/7/1 13:07:23

零信任架构下的AI分类:安全云端处理方案

零信任架构下的AI分类&#xff1a;安全云端处理方案 引言&#xff1a;当金融遇上AI分类 想象一下&#xff0c;一家银行每天要处理数万份客户上传的身份证、合同、发票等文件。传统人工分类不仅效率低下&#xff0c;还存在隐私泄露风险。而普通AI分类服务又难以满足金融行业严…

作者头像 李华
网站建设 2026/6/30 14:36:48

网络空间安全核心全景:一张思维导图盘点必会基础与技能(建议收藏)

一、前言 提到网络安全&#xff0c;一般人们将它看作是信息安全的一个分支&#xff0c;信息安全是更加广义的一个概念:防止对知识、事实、数据或能力非授权使用、误用、篡改或拒绝使用所采取的措施. 网络安全重磅福利&#xff1a;入门&进阶全套282G学习资源包免费分享&am…

作者头像 李华