在算法问题中,最大子数组和问题是一个经典问题。给定一个包含正数和负数的数组,任务是找到一个连续子数组,使得其元素之和最大。本文将介绍解决这一问题的两种常见方法:Kadane 算法和动态规划,并提供 JavaScript 实现。
问题描述
给定一个数组 arr,例如 arr = [1, -2, 3, 4, -9, 6],我们需要找到一个连续子数组,使得其元素之和最大。例如,对于上述数组,最大子数组和为 [3, 4, -9, 6],其和为 4。
方法一:Kadane 算法
Kadane 算法是一种高效的解决方案,时间复杂度为 (O(n)),空间复杂度为 (O(1))。其核心思想是通过遍历数组,动态计算当前子数组的最大和,并在遍历过程中更新全局最大和。
算法步骤:
- 初始化两个变量:
maxSum(全局最大和)和tempSum(当前子数组和)。 - 遍历数组中的每个元素:
- 将当前元素加到
tempSum中。 - 如果
tempSum大于maxSum,则更新maxSum。 - 如果
tempSum小于 0,则将其重置为 0(因为负数会拖累后续子数组的和)。
- 将当前元素加到
- 返回
maxSum。
JavaScript 实现:
function getMaxSubSum(arr) {
let maxSum = 0;
let tempSum = 0;
for (let item of arr) {
tempSum += item;
maxSum = Math.max(tempSum, maxSum);
if (tempSum < 0) tempSum = 0;
}
return maxSum;
}
let arr = [1, -2, 3, 4, -9, 6];
console.log(getMaxSubSum(arr)); // 输出: 7
方法二:动态规划
动态规划是另一种解决最大子数组和问题的方法。其核心思想是通过维护一个状态数组 dp,其中 dp[i] 表示以第 i 个元素结尾的最大子数组和。
算法步骤:
- 初始化状态数组
dp,其中dp[0]为arr[0](如果arr[0]大于 0,否则为 0)。 - 遍历数组中的每个元素:
- 计算
dp[i]的值:dp[i] = Math.max(arr[i], arr[i] + dp[i - 1])。 - 如果
dp[i]小于 0,则将其重置为 0。
- 计算
- 返回
dp数组中的最大值。
JavaScript 实现:
function getMaxSubSum(arr) {
if (!arr.length) return 0;
let dp = new Array(arr.length);
dp[0] = arr[0] > 0 ? arr[0] : 0;
for (let i = 1; i < arr.length; i++) {
dp[i] = Math.max(arr[i], arr[i] + dp[i - 1]);
if (dp[i] < 0) dp[i] = 0;
}
return Math.max(...dp);
}
let arr = [1, -2, 3, 4, -9, 6];
console.log(getMaxSubSum(arr)); // 输出: 7
方法对比
| 方法 | 时间复杂度 | 空间复杂度 | 适用场景 |
|---|---|---|---|
| Kadane 算法 | (O(n)) | (O(1)) | 适用于空间要求严格的场景 |
| 动态规划 | (O(n)) | (O(n)) | 需要记录每个位置的最大和时使用 |
总结
- Kadane 算法 是一种简洁高效的解决方案,适合大多数场景。
- 动态规划 提供了更直观的状态转移思路,适合需要记录中间结果的场景。
398

被折叠的 条评论
为什么被折叠?



