一、题目描述

二、解题思路
我们使用前缀和的思想来高效解决这个问题:
-
计算当前位置的前缀和sum(到当前元素为止的总和)
-
用当前前缀和减去之前的最小前缀和minpre,得到以当前位置结尾的子数组最大和
-
比较sum和premin,更新最小前缀和变量
-
记录过程中的最大子数组和
三、完整代码
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int sum = 0; // 当前前缀和
int result = INT_MIN; // 最大子数组和,初始化为最小整数
int minpre = 0; // 最小前缀和
for(int i = 0; i < nums.size(); i++) {
// 更新当前前缀和
sum = sum + nums[i];
// 用当前前缀和减去最小前缀和,更新最大和
result = max(result, sum - minpre);
// 更新最小前缀和(用于后续计算)
minpre = min(sum, minpre);
}
return result;
}
};
四、代码解析
1. 变量初始化
int result = INT_MIN;
-
使用 **
INT_MIN**确保即使全是负数也能正确处理 -
这个值是
<climits>中定义的,代表最小整数
2. 核心思想:最小前缀和
result = max(result, sum - minpre);
-
关键原理:最大子数组和 = 当前前缀和 - 之前的最小前缀和
-
如果我们在位置 i 有前缀和 sum[i],在位置 j (j < i) 有前缀和 sum[j]
-
那么子数组 nums[j+1...i] 的和 = sum[i] - sum[j]
-
要使子数组值最大,就需要找到最小的 sum[j],即之前的最小前缀和
3. 更新最小前缀和
minpre = min(sum, minpre);
-
在计算完当前结果后,更新最小前缀和
-
这样可以确保下次计算时使用的是当前之前的最小前缀和
-
初始时 minpre = 0,对应空子数组(前缀和为0)
五、执行示例
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
详细步骤:
| i | nums[i] | sum | minpre | sum-minpre | result |
|---|---|---|---|---|---|
| 0 | -2 | -2 | 0 | -2-0=-2 | -2 |
| 1 | 1 | -1 | -2 | -1-(-2)=1 | 1 |
| 2 | -3 | -4 | -4 | -4-(-4)=0 | 1 |
| 3 | 4 | 0 | -4 | 0-(-4)=4 | 4 |
| 4 | -1 | -1 | -4 | -1-(-4)=3 | 4 |
| 5 | 2 | 1 | -4 | 1-(-4)=5 | 5 |
| 6 | 1 | 2 | -4 | 2-(-4)=6 | 6 |
| 7 | -5 | -3 | -4 | -3-(-4)=1 | 6 |
| 8 | 4 | 1 | -4 | 1-(-4)=5 | 6 |
最终结果:6(对应子数组 [4,-1,2,1])
六、总结
本文介绍了使用前缀和和最小前缀思想求解最大子数组和的高效算法。该算法的核心在于:最大子数组和等于当前前缀和减去之前的最小前缀和。通过维护一个最小前缀和变量,我们可以在一次遍历中解决问题,时间复杂度O(n),空间复杂度O(1)。这种方法比暴力法的O(n²)和分治法的O(n log n)都要高效,是解决最大子数组和问题的最优解法。