LeetCode热题(JS版) - 152. 乘积最大子数组

172 阅读1分钟

题目

给定一个整数数组 nums ,找到一个具有最大乘积的子数组(数组中至少包含一个数字),返回该子数组所对应的乘积。

示例 1:

输入: [2,3,-2,4] 
输出: 6 
解释: 子数组 [2,3] 有最大乘积 6

示例 2:

输入: [-2,0,-1] 
输出: 0 
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。

题解

这道题可以通过动态规划来解决。设 maximax_{i}minimin_{i} 分别代表以第 ii 个数字结尾的子数组的最大值和最小值,那么状态转移方程如下:

maxi=max(numsi,maxi1numsi)max_{i} = max(nums_{i}, max_{i-1} * nums_{i})

mini=min(numsi,mini1numsi)min_{i} = min(nums_{i}, min_{i-1} * nums_{i})

其中,numsinums_{i} 为第 ii 个数字。

具体实现代码如下:

function maxProduct(nums: number[]): number {
  let max = -Infinity, imax = 1, imin = 1;
  
  for (let i = 0; i < nums.length; i++) {
    // 对负数处理
    if (nums[i] < 0) {
      [imax, imin] = [imin, imax];
    }
    // 以i结尾的子数组的最大最小值
    imax = Math.max(imax * nums[i], nums[i]);
    imin = Math.min(imin * nums[i], nums[i]);
    
    // 动态更新最大值
    max = Math.max(max, imax);
  }
  return max;
}

时间/空间复杂度

  • 时间复杂度为O(n)O(n),因为我们只需要遍历整个数组一次。
  • 空间复杂度也是O(n)O(n),因为我们需要创建两个辅助数组来存储状态变量。