LeetCode 152.乘积最大子数组

https://leetcode-cn.com/problems/maximum-product-subarray
给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。

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

思路:
在乘法中,两个负数相乘会得到正数,而负数乘正数会得到负数,也就是说,有可能上一个积是最大值,下一个就变成了最小值。所以需要记录每一次乘积的最大值和最小值。
状态定义:dp[i][0]表示从0-i子数组的最小乘积,dp[i][1]表示0到i子数组的最大乘积。
那么想要推断二者的状态转移方程,需要从三种情况考虑:
最小乘积:

  1. num[i]是正数,乘上前一个状态的最小积可以得到最小积
  2. num[i]是负数,乘上前一个状态的最大积可以得到最小积
  3. num[i]本身最小
  4. 状态方程: dp[i] [0]=min(dp[i−1] [0]∗num[i] , dp[i−1] [1] ∗ num[i], num[i])

最大乘积

  1. num[i]是正数,乘上前一个状态的最大积可以得到最大积
  2. num[i]是负数,乘上前一个状态的最小积可以得到最大积
  3. num[i]本身最大
  4. 状态方程:dp[i] [1]=max(dp[i−1] [0]∗num[i] , dp[i−1] [1] ∗ num[i], num[i])
var maxProduct = function(nums) {
        const len = nums.length;
        let dp = new Array(len).fill(0).map( () => new Array(2).fill(0) );
        let result = nums[0];

        dp[0][0] = nums[0]; //min
        dp[0][1] = nums[0]; //max

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

        return result
        
};

通过上述可知,dp[i][0]和dp[i][1]可以用两个变量表示,即状态可压缩

var maxProduct = function(nums) {
        const len = nums.length;
        let result = nums[0];

        min = nums[0]; //min
        max = nums[0]; //max

        for (let i = 1; i < len; i++) {
            let temp = min;
            min = Math.min(min * nums[i], max * nums[i], nums[i]);
            max = Math.max(max * nums[i], temp * nums[i], nums[i]);
            result = Math.max(result, max);
        }

        return result
        
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值