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

🔥个人主页: 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] 的累加和:

sumi=nums0+nums1+⋯+numsi

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

sumi−sumj

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

相关推荐
库库的数据库笔记6 分钟前
金融核心交易系统的数据库国产信创改造该如何做?
大数据·数据库·分布式·mysql·oracle·金融·数据库架构
灰山君9 分钟前
从三维数字孪生到交互式图表:山海鲸可视化与pyecharts应用解析
大数据·信息可视化·数据分析·数字孪生·3d模型
himobrinehacken29 分钟前
位运算揭秘:左右移与符号位陷阱
c语言·c++·算法·安全
Databend42 分钟前
Databend 8-9 月双月报:物化视图、数据共享与数据血缘能力升级
大数据·数据分析·agent
INGNIGHT1 小时前
815 · 课程表IV(dfs)
算法·深度优先
Databend1 小时前
周年庆结束了,湖仓为什么还在高消费?
大数据·数据库·agent
QZ166560951591 小时前
可视化易用·低误报率·跨区域部署:知源-AI数据分类分级系统在金融行业的落地实践
大数据·网络·安全·网络安全
Leo.yuan1 小时前
企业级数据治理平台选型观察:FineDataLink 5.0 在多源异构环境中的应用价值
大数据·人工智能
Pniubi1 小时前
力扣146.LRU缓存机制
算法·leetcode·缓存
云上工程笔记2 小时前
2026年7B到67B模型训练与推理GPU配置评测:LoRA、量化与全量微调对比
人工智能·算法·机器学习