LeetCode 热门100题之一:最大子数组和 💡📈
最大子数组和 是 LeetCode 上极受欢迎的一个问题,常被用于测试算法设计与优化能力。本文将详细解析该问题的定义、解题思路、具体实现及优化方法,帮助你深入理解并高效解决这一经典算法题。
问题描述 📜
给定一个 整数数组 nums
,找到 一个具有最大和的连续子数组(子数组最少包含一个元素),并返回其和。
示例:
输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
解题思路 🧠
要解决这个问题,最直观的方法是使用 动态规划,其中 Kadane 算法 是最为高效的方案,其时间复杂度为 O(n)。
Kadane 算法的核心思想是通过遍历数组,记录当前子数组的最大和,并持续更新全局最大和。
关键步骤:
初始化:
currentSum
:记录以当前元素结尾的子数组的最大和。maxSum
:记录全局的最大子数组和。
遍历数组:
- 对于每个元素,决定是将其加入当前子数组,还是单独作为一个新的子数组。
- 更新
currentSum
为max(currentSum + nums[i], nums[i])
。 - 更新
maxSum
为max(maxSum, currentSum)
。
返回结果:
- 遍历结束后,
maxSum
即为所求的最大子数组和。
- 遍历结束后,
算法实现 💻
以下是使用 Java 实现的 Kadane 算法示例:
public class Solution {
public int maxSubArray(int[] nums) {
// 初始化 currentSum 和 maxSum 为第一个元素
int currentSum = nums[0];
int maxSum = nums[0];
// 从第二个元素开始遍历
for (int i = 1; i < nums.length; i++) {
// 决定是否将当前元素加入现有子数组
currentSum = Math.max(nums[i], currentSum + nums[i]);
// 更新全局最大和
maxSum = Math.max(maxSum, currentSum);
}
return maxSum;
}
}
代码详解 📝
初始化:
int currentSum = nums[0]; int maxSum = nums[0];
currentSum
和maxSum
均初始化为数组的第一个元素,确保至少包含一个元素。
遍历数组:
for (int i = 1; i < nums.length; i++) { currentSum = Math.max(nums[i], currentSum + nums[i]); maxSum = Math.max(maxSum, currentSum); }
- 对于每个元素
nums[i]
,比较nums[i]
与currentSum + nums[i]
,选择较大者作为新的currentSum
。 - 更新
maxSum
为当前的maxSum
和currentSum
中的较大值。
- 对于每个元素
返回结果:
return maxSum;
- 最终
maxSum
即为最大子数组和。
- 最终
复杂度分析 📊
复杂度类型 | 数量级 |
---|---|
时间复杂度 | O(n) |
空间复杂度 | O(1) |
- 时间复杂度:仅需遍历一次数组,时间复杂度为 O(n)。
- 空间复杂度:使用常数空间,额外空间复杂度为 O(1)。
示例解析 🔍
让我们通过一个示例更直观地理解算法的工作原理。
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
过程:
索引 | 数值 | currentSum 计算 | maxSum 更新 |
---|---|---|---|
0 | -2 | currentSum = -2 | maxSum = -2 |
1 | 1 | max(1, -2 + 1) = 1 | maxSum = 1 |
2 | -3 | max(-3, 1 - 3) = -2 | maxSum = 1 |
3 | 4 | max(4, -2 + 4) = 4 | maxSum = 4 |
4 | -1 | max(-1, 4 - 1) = 3 | maxSum = 4 |
5 | 2 | max(2, 3 + 2) = 5 | maxSum = 5 |
6 | 1 | max(1, 5 + 1) = 6 | maxSum = 6 |
7 | -5 | max(-5, 6 - 5) = 1 | maxSum = 6 |
8 | 4 | max(4, 1 + 4) = 5 | maxSum = 6 |
最终结果:maxSum = 6
工作流程图 📈
graph TD;
A[开始] --> B[初始化 currentSum 和 maxSum 为第一个元素]
B --> C{遍历数组中的每个元素}
C -->|是| D[更新 currentSum 为 max(nums[i], currentSum + nums[i])]
D --> E[更新 maxSum 为 max(maxSum, currentSum)]
E --> C
C -->|否| F[结束遍历]
F --> G[返回 maxSum]
说明:该流程图展示了 Kadane 算法的执行流程,从初始化到遍历数组,再到更新当前和与最大和,直至结束并返回结果。
常见变种与扩展 🔄
最大子数组和 的问题有多个变种,如:
返回子数组本身:
- 除了返回和,还需返回具体的子数组。可通过记录起始和结束索引实现。
二维数组中的最大子矩阵和:
- 扩展到二维数组,常用的解法结合 Kadane 算法与前缀和技巧。
最小子数组和:
- 类似于最大子数组和,但寻找和最小的连续子数组。
总结 🎯
最大子数组和 是一个经典的动态规划问题,通过 Kadane 算法,我们能够以线性时间复杂度高效地解决。掌握此算法不仅有助于应对类似的数组问题,还为理解更复杂的动态规划问题打下坚实基础。
关键点回顾:
- 动态规划 是解决此类问题的核心。
- Kadane 算法 提供了一种简洁高效的方法。
- 理解算法的每一步 有助于灵活应用于各种变种问题。
希望本文能帮助你深入理解 最大子数组和 问题,并在实际编程中游刃有余地应用这一算法!🚀✨