152. 乘积最大子数组 dp

79 阅读2分钟

给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续 

子数组

(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。

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

 

示例 1:

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

示例 2:

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

 

提示:

  • 1 <= nums.length <= 2 * 104
  • -10 <= nums[i] <= 10
  • nums 的任何子数组的乘积都 保证 是一个 32-位 整数

求解

public int maxProduct(int[] nums) {
        //连续的最大乘积子数组--重复子问题
        //1.dp[i]定义为以元素i结尾的最大乘积
        //2.状态转移:dp[i] = dp[i-1] * nums[i]//保证成绩>dp[i-1]
        //3.dp[0] = nums[0]

        //发现因为负数的存在,上述转移公式有问题,多了个状态,再加一维
        //dp[i][0]为以i结尾最小值  dp[i][1]为以i结尾最大值

        //如果nums[i]>=0  dp[i][0] = Math.min(nums[i], dp[i - 1][0] * nums[i]);  dp[i][1] = Math.max(nums[i], dp[i - 1][1] * nums[i]);
        //如果<0  dp[i][0]= Math.min(nums[i], dp[i - 1][1] * nums[i]);  dp[i][1] = Math.max(nums[i], dp[i - 1][0] * nums[i]);  无论dp[i-1][j]是正还是负
       //最后遍历dp取最大值即可 

    }

    public class Solution {


    public int maxProduct(int[] nums) {
        int len = nums.length;
        if (len == 0) {
            return 0;
        }

        // 状态定义:以索引 i 结尾
        int[][] dp = new int[len][2];

        dp[0][0] = nums[0];
        dp[0][1] = nums[0];

        for (int i = 1; i < len; i++) {
            if (nums[i] >= 0) {
                dp[i][1] = Math.max(nums[i], dp[i - 1][1] * nums[i]);
                dp[i][0] = Math.min(nums[i], dp[i - 1][0] * nums[i]);
            } else {
                dp[i][1] = Math.max(nums[i], dp[i - 1][0] * nums[i]);
                dp[i][0] = Math.min(nums[i], dp[i - 1][1] * nums[i]);
            }
        }

        int res = dp[0][1];
        for (int i = 1; i < len; i++) {
            res = Math.max(res, dp[i][1]);
        }
        return res;
    }

}

作者:liweiwei1419
链接:https://leetcode.cn/problems/maximum-product-subarray/solutions/251440/dong-tai-gui-hua-li-jie-wu-hou-xiao-xing-by-liweiw/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    ```