返回

找出连续子数组的最大和或最小和,让你轻松掌控数据世界!

前端

前言

欢迎来到《剑指Offer》系列的开篇之作,我们将在这里共同探索“连续子数组的最大和或最小和”这个问题。作为编程面试中常见的考点,这个问题考察了我们对动态规划算法的理解和应用能力。在接下来的内容中,我们将从理解题目开始,逐步剖析算法,最终实现解决问题的代码,帮助你掌握这道经典算法题的精髓。

一、理解题目

以“连续子数组的最大和”为例,这个问题相当于让我们在数组中计算连续的子数组的和,然后在所有子数组和中找出最大值。例如,对于数组[−2, 1, −3, 4, −1, 2, 1, −5, 4],连续子数组的最大和为6,由子数组[4, -1, 2, 1]贡献。

而“连续子数组的最小和”则与此类似,只不过我们需要找到所有子数组和中的最小值。对于上述数组,连续子数组的最小和为-11,由子数组[-2, 1, -3, 4, -1, 2, 1, -5, 4]贡献。

二、剖析算法

为了解决这个问题,我们可以采用动态规划算法。动态规划算法是一种自底向上的求解方法,它将问题分解成更小的子问题,然后逐步解决这些子问题,最终得到整个问题的答案。

在解决连续子数组最大和/最小和的问题时,我们可以定义一个状态变量dp[i],表示以第i个元素结尾的连续子数组的最大和/最小和。然后,我们可以使用以下递推公式来计算dp[i]:

dp[i] = max/min(dp[i-1] + nums[i], nums[i])

其中,nums[i]表示数组的第i个元素。

三、实现代码

/**
 * 寻找连续子数组的最大和或最小和
 *
 * @param {number[]} nums 输入数组
 * @param {boolean} isMax 是否寻找最大和
 * @returns {number} 连续子数组的最大和或最小和
 */
const maxSubArraySum = (nums, isMax) => {
  // 初始化状态变量
  const dp = new Array(nums.length).fill(0);
  dp[0] = nums[0];

  // 遍历数组,计算每个状态变量
  for (let i = 1; i < nums.length; i++) {
    dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]);
  }

  // 返回最大或最小和
  return isMax ? Math.max(...dp) : Math.min(...dp);
};

四、示例

// 示例数组
const nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4];

// 寻找连续子数组的最大和
const maxSum = maxSubArraySum(nums, true);
console.log(`连续子数组的最大和:${maxSum}`); // 输出:6

// 寻找连续子数组的最小和
const minSum = maxSubArraySum(nums, false);
console.log(`连续子数组的最小和:${minSum}`); // 输出:-11

五、结语

通过学习“连续子数组的最大和或最小和”这个问题,我们不仅掌握了动态规划算法的应用技巧,还加深了对数组操作和算法分析的理解。希望这篇文章能帮助你对动态规划算法有更深入的了解,并在未来的编程实践中灵活运用。

六、扩展阅读