news 2026/5/24 14:03:19

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

作者头像

张小明

前端开发工程师

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/5/13 12:26:40

Kubernetes Pod 入门

前言 如果你刚接触 Kubernetes&#xff08;简称 K8s&#xff09;&#xff0c;那一定绕不开 “Pod” 这个核心概念。Pod 是 K8s 集群里最小的部署单元&#xff0c;就像一个 “容器工具箱”—— 它不直接跑业务&#xff0c;而是把容器和集群的网络、存储资源打包在一起&#xff0…

作者头像 李华
网站建设 2026/5/1 6:09:01

中文命名实体识别高性能方案|AI智能侦测服务镜像发布

中文命名实体识别高性能方案&#xff5c;AI智能侦测服务镜像发布 1. 背景与需求&#xff1a;中文NER的挑战与突破 在信息爆炸的时代&#xff0c;非结构化文本数据&#xff08;如新闻、社交媒体、企业文档&#xff09;占据了数据总量的80%以上。如何从这些杂乱文本中自动提取关…

作者头像 李华
网站建设 2026/5/9 17:18:45

Qwen3-VL-WEBUI镜像优势解析|附Qwen2-VL同款部署与测试案例

Qwen3-VL-WEBUI镜像优势解析&#xff5c;附Qwen2-VL同款部署与测试案例 1. 引言&#xff1a;为何选择Qwen3-VL-WEBUI镜像&#xff1f; 随着多模态大模型在视觉理解、图文生成和跨模态推理等任务中的广泛应用&#xff0c;开发者对高效、易用且功能强大的部署方案需求日益增长。…

作者头像 李华
网站建设 2026/5/1 6:55:25

如何高效接入视觉大模型?Qwen3-VL-WEBUI部署与API调用指南

如何高效接入视觉大模型&#xff1f;Qwen3-VL-WEBUI部署与API调用指南 在某智能客服系统的后台&#xff0c;一张用户上传的APP界面截图刚被接收&#xff0c;系统不到五秒就返回了结构化建议&#xff1a;“检测到‘提交订单’按钮处于禁用状态&#xff0c;可能是库存不足或未登…

作者头像 李华
网站建设 2026/5/22 16:23:53

MiDaS部署技巧:如何实现高效的CPU推理

MiDaS部署技巧&#xff1a;如何实现高效的CPU推理 1. 引言&#xff1a;AI 单目深度估计的现实挑战 在计算机视觉领域&#xff0c;从单张2D图像中恢复3D空间结构一直是极具挑战性的任务。传统方法依赖多视角几何或激光雷达等硬件支持&#xff0c;成本高且部署复杂。近年来&…

作者头像 李华
网站建设 2026/5/21 2:43:42

Qwen3-VL-WEBUI镜像深度解析|从GitHub镜像快速拉取并运行视觉大模型

Qwen3-VL-WEBUI镜像深度解析&#xff5c;从GitHub镜像快速拉取并运行视觉大模型 在多模态人工智能迅猛发展的今天&#xff0c;视觉-语言模型&#xff08;VLM&#xff09;已不再局限于“看图说话”的初级阶段&#xff0c;而是逐步演进为具备复杂推理、空间感知和任务执行能力的…

作者头像 李华