力扣第152题-乘积最大子数组

135 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第19天,点击查看活动详情

前言

力扣第152题 乘积最大子数组 如下所示:

给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。

测试用例的答案是一个 32-位 整数。

子数组 是数组的连续子序列。

示例 1:

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

一、思路

题目很简短,也很好理解,就是找到数组中 乘积最大的非空连续子数组。既然说到 乘积最大,我们直到 正正得正,负负得正。假设需要求以 nums[i] 结尾的乘积最大子数组,只会有以下几种情况之一:

  • nums[i] 为正数:则找到以 nums[i-1] 结尾的子数组最大的乘积乘上 nums[i]nums[i] 中,取最大的值保留
  • nums[i] 为负数:则找到以 nums[i-1] 结尾的最小乘积(负数)

对上述中 nums[i] 为正数做个特殊解释,此处以 nums = [0, 2] 作为例子。很明显以 nums[1] 为结尾的最大乘积为 2,即nums[1] 本身。如果乘上以 nums[0] 为结尾的最大乘积 0 反而会更小。

上面的这个过程,说明求最大乘积的过程是可以分解的,故在这里可以使用 动态规划。我们的目的只有一个 求以 nums[i] 为结尾的最大乘积和最小乘积(负数),因为 负数 x 最小的负数 会得到 最大的正数

positiveMax[i]:以 nums[i] 为结尾的最大乘积 negativeMin[i]:以 nums[i] 为结尾的最小乘积(负数)

可以推到出如下的动态规划:

  • nums[i] > 0
    • positiveMax[i] = Math.max(positiveMax[i-1] x nums[i], nums[i])
    • negativeMin[i] = negativeMin[i-1] x nums[i]
  • nums[i] <= 0
    • positiveMax[i] = negativeMin[i-1] x nums[i]
    • negativeMin[i] = Math.min(positiveMax[i-1] x nums[i], nums[i])

上面分了正负两种情况讨论,需要注意:正数时可能会取 nums[i] 本身,负数时也是同理。

二、实现

实现代码

实现代码与思路中保持一致

public int maxProduct(int[] nums) {
    int ret = nums[0];
    int len = nums.length;
    int[] positiveMax = new int[len];    // 正数最大值
    int[] negativeMin = new int[len];
    if (nums[0] > 0)
        positiveMax[0] = nums[0];
    else
        negativeMin[0] = nums[0];
    for (int i = 1; i < len; ++i) {
        if (nums[i] > 0){
            positiveMax[i] = Math.max(positiveMax[i-1] * nums[i], nums[i]);
            negativeMin[i] = negativeMin[i-1] * nums[i];
        } else {    // 负数
            positiveMax[i] = negativeMin[i-1] * nums[i];
            negativeMin[i] = Math.min(positiveMax[i-1] * nums[i], nums[i]);
        }
        ret = Math.max(positiveMax[i], ret);
    }
    return ret;
}

测试代码

public static void main(String[] args) {
    int[] nums = {2,3,-2,4};
    int[] nums1 = {0, 2};
    new Number152().maxProduct(nums1);
}

结果

image.png

三、总结

感谢看到最后,非常荣幸能够帮助到你~♥

如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~