力扣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算法更简洁常用
  • 前缀和法在需复用前缀信息时更灵活(如解决子矩阵最大和等问题)

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

相关推荐
HZY1618yzh2 分钟前
下一代编程语言出炉
c++·算法
深盾科技_Virbox2 分钟前
云端与本地并行交付,软件许可管理如何实现统一运营?
java·大数据·开发语言·安全
thefool1122663 分钟前
多线程 3
java
Thneonl9 分钟前
别上来就 strace:60 秒十条命令看清一台病机
后端·程序员
CoderYanger9 分钟前
A.每日一题:856. 括号的分数
java·程序人生·算法·leetcode·面试·职场和发展·学习方法
马剑威(威哥爱编程)18 分钟前
【AI全栈后端12-11】Spring Boot 把 AI 接口真正上线扛量:限流 / 降级 / 可观测
人工智能·spring boot·后端
kiracrimson23 分钟前
选择排序与快速排序:一次选极值,一次分区间
算法·排序算法
liangbo726 分钟前
01-Java 集合框架全景:从 Collection 到 Map 一张关系网理清
java
xuxigifxfh29 分钟前
HJ15 求int型正整数在内存中存储时1的个数
java·开发语言·华为机考
Wokoo733 分钟前
自动化测试入门:核心场景、回归测试与 Web 自动化环境搭建
java·开发语言·测试工具