力扣hot100:最大子数组和的两种高效方法:前缀和与Kadane算法(53)

最大子数组和问题是算法中的一个经典问题,即在给定整数数组中寻找连续子数组使其和达到最大(子数组不能为空)。本文将详细解析两种时间复杂度为 O(n)、空间复杂度为 O(1) 的精妙解法,并附上完整 Java 实现。

问题示例

给定数组 [-2,1,-3,4,-1,2,1,-5,4],最大子数组和为 [4,-1,2,1],其和为 6

方法一:前缀和法(Prefix Sum)

核心思想

通过动态计算数组前缀和,并维护当前最小前缀和,用当前前缀和减去最小前缀和得到局部最大子数组和。

算法步骤
  1. 初始化 temp 为当前前缀和(初始值为0)
  2. 初始化 min 为最小前缀和(初始值为0)
  3. 遍历数组:
    • 更新当前前缀和 temp += num
    • 计算当前子数组和:temp - min
    • 更新全局最大值 result
    • 更新最小前缀和 min
java 复制代码
public int maxSubArrayT1(int[] nums) {
    int temp = 0;
    int min = 0;
    int result = Integer.MIN_VALUE;
    for (int num : nums) {
        temp += num;             // 更新当前前缀和
        result = Math.max(result, temp - min); // 更新全局最大值
        min = Math.min(temp, min);    // 更新最小前缀和
    }
    return result;
}
示例分析

[-2,1,-3] 为例:

步骤 num temp min temp-min result
初始 - 0 0 - MIN
1 -2 -2 -2 -2-0=-2 -2
2 1 -1 -2 -1-(-2)=1 1
3 -3 -4 -4 -4-(-2)=-2 1(保持)

方法二:Kadane算法(动态规划)

核心思想

通过动态维护当前连续子数组和,当和小于等于0时丢弃该子数组(因其无法增大后续和),同时全程更新最大值。

算法步骤
  1. 初始化 temp 为当前子数组和(初始值为0)
  2. 初始化 max 为全局最大值(初始值为 Integer.MIN_VALUE
  3. 遍历数组:
    • temp += nums[i](累加当前值)
    • 更新 max = Math.max(max, temp)
    • temp <= 0,重置 temp = 0(丢弃负贡献子数组)
java 复制代码
public int maxSubArrayT2(int[] nums) {
    int max = Integer.MIN_VALUE;
    int temp = 0;
    for (int num : nums) {
        temp += num;          // 累加当前值
        max = Math.max(max, temp);  // 更新全局最大值
        if (temp <= 0) temp = 0;    // 若和为负则重置
    }
    return max;
}
示例分析

[-2,1,-3] 为例:

步骤 num temp max 操作
初始 - 0 MIN -
1 -2 -2 -2 temp<=0 → 重置为0
2 1 0+1=1 max(-2,1)=1 -
3 -3 1-3=-2 max(1,-2)=1 temp<=0 → 重置为0

方法对比与总结

特性 前缀和法 Kadane算法
核心思想 前缀和与最小值差值 动态丢弃负和子数组
重置条件 无显式重置 temp<=0 时重置
适用场景 需处理前缀和问题时 标准最大子数组问题
优势 直观易扩展 代码更简洁

关键共同点

  • 时间复杂度 O(n)(只需一次遍历)
  • 空间复杂度 O(1)(仅用常数变量)
  • 均能正确处理全负数数组(如 [-3,-1,-2] 返回 -1

两种方法都是高效解法,在实际面试或解题中:

  • Kadane算法更简洁常用
  • 前缀和法在需复用前缀信息时更灵活(如解决子矩阵最大和等问题)

两种解法简洁优雅,体现了算法设计中"维护关键状态,避免重复计算"的核心思想。理解其内在逻辑后,你能轻松应对各类子数组相关问题!

相关推荐
HXhlx15 小时前
CART决策树基本原理
算法·机器学习
用户605723748730816 小时前
AI 编码助手的规范驱动开发 - OpenSpec 初探
前端·后端·程序员
哈密瓜的眉毛美16 小时前
零基础学Java|第二篇:Java 核心机制与第一个程序:从 JVM 到 Hello World
后端
用户83071968408216 小时前
RabbitMQ vs RocketMQ 事务大对决:一个在“裸奔”,一个在“开挂”?
后端·rabbitmq·rocketmq
初次攀爬者16 小时前
RocketMQ 集群介绍
后端·消息队列·rocketmq
Wect16 小时前
LeetCode 210. 课程表 II 题解:Kahn算法+DFS 双解法精讲
前端·算法·typescript
初次攀爬者16 小时前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq
Leo89916 小时前
go 从零单排 之 一小时通关
后端
花花无缺16 小时前
搞懂@Autowired 与@Resuorce
java·spring boot·后端
CodeMonkey16 小时前
记一次傻逼一样的 OOM 异常
后端