如何找到连续子数组的最大和:Kadane 算法详解

在算法问题中,最大子数组和问题是一个经典问题。给定一个包含正数和负数的数组,任务是找到一个连续子数组,使得其元素之和最大。本文将介绍解决这一问题的两种常见方法:Kadane 算法动态规划,并提供 JavaScript 实现。


问题描述

给定一个数组 arr,例如 arr = [1, -2, 3, 4, -9, 6],我们需要找到一个连续子数组,使得其元素之和最大。例如,对于上述数组,最大子数组和为 [3, 4, -9, 6],其和为 4


方法一:Kadane 算法

Kadane 算法是一种高效的解决方案,时间复杂度为 (O(n)),空间复杂度为 (O(1))。其核心思想是通过遍历数组,动态计算当前子数组的最大和,并在遍历过程中更新全局最大和。

算法步骤:
  1. 初始化两个变量:maxSum(全局最大和)和 tempSum(当前子数组和)。
  2. 遍历数组中的每个元素:
    • 将当前元素加到 tempSum 中。
    • 如果 tempSum 大于 maxSum,则更新 maxSum
    • 如果 tempSum 小于 0,则将其重置为 0(因为负数会拖累后续子数组的和)。
  3. 返回 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 个元素结尾的最大子数组和。

算法步骤:
  1. 初始化状态数组 dp,其中 dp[0]arr[0](如果 arr[0] 大于 0,否则为 0)。
  2. 遍历数组中的每个元素:
    • 计算 dp[i] 的值:dp[i] = Math.max(arr[i], arr[i] + dp[i - 1])
    • 如果 dp[i] 小于 0,则将其重置为 0。
  3. 返回 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 算法 是一种简洁高效的解决方案,适合大多数场景。
  • 动态规划 提供了更直观的状态转移思路,适合需要记录中间结果的场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值