普通数组----最大子数组和

🔥个人主页: Milestone-里程碑

❄️个人专栏: <<力扣hot100>> <<C++>><<Linux>>

<<Git>><<MySQL>>

🌟心向往之行必能至

一、题目背景

LeetCode 53 题「最大子数组和」是算法面试中的经典问题,属于动态规划与前缀和的典型应用。题目要求在给定整数数组中,找到一个连续子数组(最少包含一个元素),使其和最大并返回该值。

例如:

  • 输入 nums = [-2,1,-3,4,-1,2,1,-5,4],输出 6(对应子数组 [4,-1,2,1])。
  • 输入 nums = [5,4,-1,7,8],输出 23(对应子数组 [5,4,-1,7,8])。

这道题不仅考察算法思维,还能帮助理解「前缀和」「动态规划」等核心概念,是大厂面试的高频考点。

二、核心思路:前缀和 + 最小前缀和

1. 前缀和的定义

对于数组 nums,定义前缀和数组 sum,其中 sum[i] 表示从 nums[0]nums[i] 的累加和:

sum[i]=nums[0]+nums[1]+⋯+nums[i]

那么,子数组 nums[j+1 ... i] 的和可以表示为:

sum[i]−sum[j]

我们的目标是找到 j < i,使得 sum[i] - sum[j] 最大。

2. 转化问题:找最小前缀和

对于每个 i,要让 sum[i] - sum[j] 最大,等价于找到最小的 sum[j](其中 j < i

因此,我们可以维护两个变量:

  • sum:当前的前缀和(sum[i])。
  • min_sum:遍历到当前位置时,最小的前缀和(min{sum[0], sum[1], ..., sum[i-1]})。

每遍历一个元素,我们先更新当前前缀和 sum,然后计算 sum - min_sum(即当前子数组的最大可能和),并维护全局最大值 Max。最后更新 min_sum 为当前最小的前缀和。

3. 初始值的关键设置

  • sum 初始化为 0,表示前缀和从空数组开始累加。
  • min_sum 初始化为 0,对应 sum[-1] = 0(空数组的前缀和),确保第一个元素也能正确计算。
  • Max 初始化为 INT_MIN,处理数组全为负数的情况(例如 nums = [-5,-3,-2],最大子数组和为 -2)。

三、代码实现(C++)

cpp

运行

复制代码
#include <vector>
#include <climits>
using namespace std;

class Solution {
public:
    // 子数组可以看成子数组最右边的前缀和减去它前面的最小前缀和
    int maxSubArray(vector<int>& nums) {
        int sum = 0;
        int Max = INT_MIN;
        int min_sum = 0;
        for (int i = 0; i < nums.size(); ++i) {
            sum += nums[i];
            Max = max(Max, sum - min_sum); // 计算当前子数组的最大和
            min_sum = min(min_sum, sum);   // 更新最小前缀和
        }
        return Max;
    }
};

四、代码逐行解析

  1. 变量初始化

    • sum = 0:当前前缀和,初始为空数组的和。
    • Max = INT_MIN:全局最大子数组和,初始为最小整数,确保能正确更新负数情况。
    • min_sum = 0:最小前缀和,初始为空数组的和。
  2. 遍历数组

    • sum += nums[i]:累加当前元素,更新前缀和。
    • Max = max(Max, sum - min_sum):计算以当前元素结尾的子数组的最大和(当前前缀和减去之前的最小前缀和),并更新全局最大值。
    • min_sum = min(min_sum, sum):更新最小前缀和,确保后续计算能用到更小的前缀和。
  3. 返回结果 :遍历结束后,Max 即为整个数组的最大子数组和。

五、示例验证(以 nums = [-2,1,-3,4,-1,2,1,-5,4] 为例)

索引 i nums[i] sum(前缀和) sum - min_sum Max min_sum
0 -2 -2 -2 - 0 = -2 -2 min(0,-2)=-2
1 1 -1 -1 - (-2) = 1 1 min(-2,-1)=-2
2 -3 -4 -4 - (-2) = -2 1 min(-2,-4)=-4
3 4 0 0 - (-4) = 4 4 min(-4,0)=-4
4 -1 -1 -1 - (-4) = 3 4 min(-4,-1)=-4
5 2 1 1 - (-4) = 5 5 min(-4,1)=-4
6 1 2 2 - (-4) = 6 6 min(-4,2)=-4
7 -5 -3 -3 - (-4) = 1 6 min(-4,-3)=-4
8 4 1 1 - (-4) = 5 6 min(-4,1)=-4

最终,Max = 6,与示例输出一致。

六、复杂度分析

  • 时间复杂度O(n),仅需遍历数组一次,每个元素的操作都是常数时间。
  • 空间复杂度O(1),仅使用了常数个变量,未额外开辟数组空间。

七、解法对比

解法 时间复杂度 空间复杂度 适用场景
前缀和 + 最小前缀和 O(n) O(1) 追求时间、空间效率最优
Kadane 算法(动态规划) O(n) O(1) 直观理解「当前子数组和是否延续」
分治法 O(n log n) O(log n) 理解分治思想,适合教学场景

前缀和 + 最小前缀和的解法与 Kadane 算法效率相同,但思路更偏向数学推导,适合从前缀和的角度理解问题。

八、总结

LeetCode 53 题的核心是将「最大子数组和」转化为「前缀和的差值最大化」问题,通过维护最小前缀和,在一次遍历中完成计算,时间和空间复杂度均为最优。这种思路不仅能解决本题,还可拓展到类似的子数组和问题(如返回子数组的起始 / 结束索引)。

相关推荐
IT猿手4 分钟前
SCI一区:章鱼优化算法(Octopus Optimization Algorithm, OOA)求解23个测试函数,出图丰富,提供完整MATLAB代码
开发语言·算法·matlab
superior tigre5 分钟前
739 每日温度
算法·leetcode·职场和发展
忡黑梨9 分钟前
eNSP_从直连到BGP全网互通
c语言·网络·数据结构·python·算法·网络安全
瑞华丽PLM14 分钟前
传统研发协同低效痛点待解,PLM 系统数字化选型助力研发效率提升与转型
大数据·plm·国产plm·瑞华丽plm·瑞华丽
Run_Teenage24 分钟前
算法:离散化模板
算法
乐迪信息24 分钟前
乐迪信息:实时预警,秒级响应:船舶AI异常行为检测算法
大数据·人工智能·算法·安全·目标跟踪
6Hzlia27 分钟前
【Hot 100 刷题计划】 LeetCode 15. 三数之和 | C++ 排序+双指针
c++·算法·leetcode
红色星际27 分钟前
进军具身机器人和Robotaxi的智驾公司
大数据·人工智能·机器人
Bruce_Liuxiaowei28 分钟前
《轻量化制播系统技术应用指南(2026版)》解读:县级融媒体的“减负增效“新路径
大数据·人工智能·媒体
fox_lht30 分钟前
第十章 通用集合
开发语言·后端·算法·rust