跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava算法

最大子数组和算法解析:暴力、动态规划与贪心(Java)

介绍最大子数组和问题,提供三种解法:暴力枚举时间复杂度 O(n²),动态规划优化至 O(n) 空间可优化至 O(1),以及贪心算法同样 O(n)。重点讲解状态定义、转移方程及负数边界处理,并给出 Java 代码实现与常见陷阱分析。

JavaCoder发布于 2026/3/30更新于 2026/5/2832 浏览
最大子数组和算法解析:暴力、动态规划与贪心(Java)

题目描述

给你一个整数数组 nums,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组是数组中的一个连续部分。

示例 1

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6。

示例 2

输入:nums = [1]
输出:1

示例 3

输入:nums = [5,4,-1,7,8]
输出:23

核心考点

  • 贪心算法的应用(局部最优推导全局最优);
  • 动态规划的状态定义与转移;
  • 时间复杂度的优化(从 O(n²) 到 O(n))。

解题思路

1. 暴力解法

遍历所有可能的连续子数组,计算每个子数组的和,记录最大值。

具体步骤:

  1. 外层循环控制子数组的起始位置(i 从 0 到 nums.length-1);
  2. 内层循环控制子数组的结束位置(j 从 i 到 nums.length-1);
  3. 在遍历过程中,累加子数组的和(从 i 到 j),并实时更新最大和;
  4. 遍历结束后,返回最大和。

优点:逻辑简单,容易理解。 缺点:时间复杂度 O(n²),当数组长度较大时会超时。

2. 动态规划

动态规划的核心是'状态定义'和'状态转移方程'。

第一步:定义状态 设 dp[i] 表示'以第 i 个元素结尾的连续子数组的最大和'。

第二步:推导状态转移方程 对于第 i 个元素,有两种选择:

  • 将第 i 个元素加入到以 i-1 结尾的子数组中(即 dp[i-1] + nums[i]);
  • 不加入前序子数组,单独以第 i 个元素作为新的子数组(即 nums[i])。

取两者中的最大值: dp[i] = max(dp[i-1] + nums[i], nums[i])

第三步:初始化与结果计算

  • 初始化:dp[0] = nums[0];
  • 结果:遍历 dp 数组,取其中的最大值。

优化点:不用额外开辟 dp 数组,用一个变量临时存储 dp[i-1] 的值,将空间复杂度从 O(n) 优化到 O(1)。

3. 贪心算法

贪心算法的核心是'局部最优解推导全局最优解'。当前子数组的和为负数时,放弃这个子数组,重新开始计算。

具体逻辑:

  • 定义两个变量:currentSum(当前子数组的和)、maxSum(全局最大和);
  • 遍历数组,每次将当前元素加入 currentSum;
  • 如果 currentSum > maxSum,更新 maxSum;
  • 如果 currentSum < 0,说明当前子数组的和已经是负数,继续往后加只会更小,因此将 currentSum 重置为 0(或当前元素);
  • 遍历结束后,返回 maxSum。
  • 注意:当数组中所有元素都是负数时,需特殊处理(如初始化为第一个元素)。

    代码实现

    解法 1:暴力解法(参考)

    class Solution {
        public int maxSubArray(int[] nums) {
            int n = nums.length;
            int maxSum = nums[0];
            for (int i = 0; i < n; i++) {
                int currentSum = 0;
                for (int j = i; j < n; j++) {
                    currentSum += nums[j];
                    if (currentSum > maxSum) {
                        maxSum = currentSum;
                    }
                }
            }
            return maxSum;
        }
    }
    // 时间复杂度:O(n²),空间复杂度:O(1)
    

    解法 2:动态规划(推荐)

    class Solution {
        public int maxSubArray(int[] nums) {
            int n = nums.length;
            if (n == 0) return 0;
            int preSum = nums[0];
            int maxSum = nums[0];
            for (int i = 1; i < n; i++) {
                preSum = Math.max(preSum + nums[i], nums[i]);
                maxSum = Math.max(maxSum, preSum);
            }
            return maxSum;
        }
    }
    // 时间复杂度:O(n),空间复杂度:O(1)
    

    解法 3:贪心算法(推荐)

    class Solution {
        public int maxSubArray(int[] nums) {
            int n = nums.length;
            if (n == 0) return 0;
            int currentSum = nums[0];
            int maxSum = nums[0];
            for (int i = 1; i < n; i++) {
                currentSum = Math.max(currentSum + nums[i], nums[i]);
                maxSum = Math.max(maxSum, currentSum);
            }
            return maxSum;
        }
    }
    // 时间复杂度:O(n),空间复杂度:O(1)
    

    关键细节

    1. 数组全为负数的情况:必须将 maxSum 初始化为 nums[0],避免结果为 0。
    2. 子数组的连续性:必须是连续的,不能跳过元素。
    3. 贪心算法的重置时机:只有当 currentSum 为负数时,才重置为当前元素。
    4. 动态规划的状态定义:必须是'以第 i 个元素结尾',否则无法保证连续性。

    拓展思考

    • 要求返回最大子数组的起始和结束索引;
    • 最大子数组和的个数;
    • 二维数组的最大子数组和。

    其中,'返回最大子数组的起始和结束索引'是最常考的延伸,可基于贪心或动态规划修改代码实现。

    总结

    最大子数组和是贪心和动态规划的经典入门题。

    • 暴力解法:效率低,适合入门;
    • 动态规划:通过状态定义和转移方程,实现 O(n) 时间复杂度,空间可优化到 O(1);
    • 贪心算法:逻辑简洁,效率最高。

    建议先动手写一遍暴力解法,再逐步优化,注意规避常见坑(全负数、连续性)。

    目录

    1. 题目描述
    2. 示例 1
    3. 示例 2
    4. 示例 3
    5. 核心考点
    6. 解题思路
    7. 1. 暴力解法
    8. 2. 动态规划
    9. 3. 贪心算法
    10. 代码实现
    11. 解法 1:暴力解法(参考)
    12. 解法 2:动态规划(推荐)
    13. 解法 3:贪心算法(推荐)
    14. 关键细节
    15. 拓展思考
    16. 总结
    • 💰 8折买阿里云服务器限时8折了解详情
    • Magick API 一键接入全球大模型注册送1000万token查看
    • 🤖 一键搭建Deepseek满血版了解详情
    • 一键打造专属AI 智能体了解详情
    极客日志微信公众号二维码

    微信扫一扫,关注极客日志

    微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

    更多推荐文章

    查看全部
    • llama.cpp 安装和配置指南
    • Python 面向对象编程入门:初识对象
    • Flutter mediapipe_core 鸿蒙化适配指南:端侧 AI 推理与视觉任务集成
    • 基于 UDP 协议的手机通话语音局域网传输 Python 脚本
    • 本地 AI 电话机器人:通过 UDP 传输手机通话声音的 Python 脚本
    • LazyLLM 框架实战:代码专家智能体进阶模块开发指南
    • 基于 Java Web 的驾校考试管理系统设计与实现
    • 弃用 GitHub Copilot 30 天:主流 AI 编程工具对比与选型建议
    • LangChain 教程:LLMChain 构建与应用详解
    • 自然语言处理在金融领域的应用与实战
    • 青少年软件编程 Python 等级考试一级解析
    • Ubuntu 22.04 安装 Docker 及 Docker Compose v2 教程
    • SpringBoot+Vue 学生评奖评优管理系统设计与实现
    • 渐进式 AIGC 系统:支持 Nano-Banana 绘画、VEO3/Sora-2 视频及 Agent 智能体
    • Node-RED 用户登录、鉴权与权限控制流程解析
    • JDK-17 安装与配置教程
    • Git-RSCLIP 镜像免配置部署:解决 PyTorch 与 transformers 环境冲突
    • Go 语言字符串反转算法实现
    • DevEco Studio 使用指南:HarmonyOS Next 云侧工程部署
    • AI 产品经理就业方向与转行指南:核心技能与薪资分析

    相关免费在线工具

    • Keycode 信息

      查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

    • Escape 与 Native 编解码

      JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

    • JavaScript / HTML 格式化

      使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

    • JavaScript 压缩与混淆

      Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

    • 加密/解密文本

      使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

    • Gemini 图片去水印

      基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online