LeetCode-152. 乘积最大子数组

古城微笑少年丶 2024-03-24 17:27 220阅读 0赞

目录

    • 思路
    • 动态规划

题目来源
152. 乘积最大子数组

思路

这题跟LeetCode-53. 最大子数组和很像
最后把整个 dp 数组看一遍求最大值即可。因此状态转移方程可能是:

  1. dp[i] = Math.max(dp[i-1]+nums[i],nums[i]);

说明:牢记状态的定义,一定以下标 i 结尾,即:乘积数组中 nums[i] 必须被选取。

如果 dp[i - 1] 是负数,乘上 nums[i] 还是负数。
如果 nums[i] 是负数该怎么办呢?dp[i - 1] 是正数的时候,越乘越小,dp[i - 1] 是负数的时候,越乘越大,于是我们可能就需要记录一下负数的那个最小数。
遇到这样的问题,其实就在提示我们状态不够用了。因此,需要在原来的一维 dp 后面新增一个状态。
针对这道题,第 2 维状态只需要两个:

  • dp[i][1] 表示:以 nums[i] 结尾的连续子序列的乘积的最大值;
    用 1 表示遍历的过程中得到的以 nums[i] 结尾的连续子序列的乘积的最大值。
  • dp[i][0] 表示:以 nums[i] 结尾的连续子序列的乘积的最小值。
    用 0 表示遍历的过程中得到的以 nums[i] 结尾的连续子序列的乘积的最小值;

动态规划

  • 1.确定dp数组以及下标的含义

dp[i][2]:包括下标i(以nums[i]为结尾)的乘积最大子数组积为dp[i]。

  • 2.确定递推公式

我们要收集自己本身,之前的最大值×当前数,之前的最小值×当前数

  1. dp[i][1] = Math.max(nums[i],Math.max(dp[i-1][1]*nums[i],dp[i-1][0]*nums[i]));
  2. dp[i][0] = Math.min(nums[i],Math.min(dp[i-1][1]*nums[i],dp[i-1][0]*nums[i]));
  • 3.dp数组如何初始化

根据递推公式可知,可以推出我们要初始化dp[0][0]和dp[0][1]为当前数nums[0]
dp[0][0] = nums[0];
dp[0][1] = nums[0];

  • 4.确定遍历顺序

根据递推公式可知,从左到右遍历

  • 5.举例推导dp数组

在这里插入图片描述

代码实现

  1. class Solution {
  2. public int maxProduct(int[] nums) {
  3. int[][] dp = new int[nums.length][2];
  4. dp[0][0] = nums[0];
  5. dp[0][1] = nums[0];
  6. int res = nums[0];
  7. for(int i = 1;i<nums.length;i++){
  8. dp[i][1] = Math.max(nums[i],Math.max(dp[i-1][1]*nums[i],dp[i-1][0]*nums[i]));
  9. dp[i][0] = Math.min(nums[i],Math.min(dp[i-1][1]*nums[i],dp[i-1][0]*nums[i]));
  10. res = Math.max(res,dp[i][1]);
  11. }
  12. return res;
  13. }
  14. }

在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,220人围观)

还没有评论,来说两句吧...

相关阅读

    相关 152. 乘积数组

    打卡!!!每日一题 今天继续为大家分享一道动态规划类型的题目。 题目描述: > 给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一

    相关 152.乘积数组

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