dp--152. 乘积最大的子数组/medium 理解度B

1、题目

给你一个整数数组 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-位 整数
Related Topics
  • 数组
  • 动态规划

2、题目分析

动态规划的解决套路可分为 2 步,①基于问题能定义出状态,②状态间具备动态规划的三个特性

①基于问题定义出状态:(参考该文完成分析:dp–139. 单词拆分 https://blog.csdn.net/fujuacm/article/details/135408092)

②状态间具备动态规划的三个特性(参考该文完成分析:dp–139. 单词拆分 https://blog.csdn.net/fujuacm/article/details/135408092)

  1. 重复子问题且重复策略
    重复子问题:
  2. 最优子结构
    重复策略&最优子结构:
  3. 无后效性
    更前的状态不影响当前状态:
    后面的状态不影响当前状态:

3、解题步骤

dp五部曲
1.定义dp数组以及下标的含义
dp[i][0],表示截止到第i个元素,数组中乘积最大的非空连续子数组
dp[i][1],表示截止到第i个元素,数组中乘积最小的非空连续子数组

2.推导状态转移方程(考虑3个特性:重复子问题、最优子结构、无后效性)
// 当 nums[i] > 0时,当前状态最大值仍然是前一个状态的最大值nums[i]。
// 当前状态最小值也仍然是前一个状态的最小值
nums[i]。
dp[i][0] = Math.max(dp[i - 1][0] * nums[i], nums[i]) nums[i] >= 0
dp[i][1] = Math.min(dp[i - 1][1] * nums[i], nums[i]) nums[i] >= 0

// 当 nums[i] < 0时,当前状态最大值反而是前一个状态的最小值nums[i]。
// 当前状态最小值反而是前一个状态的最大值
nums[i]。
dp[i][0] = Math.max(dp[i - 1][1] * nums[i], nums[i]) num[i] < 0
dp[i][1] = Math.min(dp[i - 1][0] * nums[i], nums[i]) num[i] < 0

3.初始化dp数组
dp数组,初始化 dp[0][0] = 1、dp[0][1] = 1,表示当数组没有元素时,乘积默认为1,后续状态的乘积不受dp[0]影响。dp其余位置设置为0

4.确定遍历顺序(二维dp可以通过 状态转移方程+4宫格明确i、j遍历顺序)
i从1到n。即从第1个字符推导到最后1个字符

5.举例推导dp数组

4、复杂度最优解代码示例

    // 乘积最大的子数组
    public int maxProduct(int[] nums) {
        int max = nums[0]; // 记录当前最大值
        int min = nums[0]; // 记录当前最小值
        int res = nums[0]; // 记录最终结果
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] < 0) { // 如果当前数为负数,交换最大值和最小值
                int temp = max;
                max = min;
                min = temp;
            }
            max = Math.max(nums[i], max * nums[i]); // 更新最大值
            min = Math.min(nums[i], min * nums[i]); // 更新最小值
            res = Math.max(res, max); // 更新最终结果
        }
        return res;
    }

5、抽象与扩展

通用动态规划的解法,见标题二

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值