152. Maximum Product Subarray

1、Description
在这里插入图片描述

2、题解思路
对于该问题,需要与之前的最大子段和进行区别,最大值段和产生以nums[i]元素结尾的局部最大值maxVal[i]的时候,只需要获取maxVal[i-1]+nums[i]和nums[i]之间的较大值即可。而该问题为最大子段乘积问题,如果所给的数全都为正整数,那么其递推方程的定义与最大子和是一样的,只不过把加号换成了乘号,然而对于该问题所给的元素也有可能是负数,所以需要考虑负数乘以负数有可能会产生更大的数的情况,为此除了维护一个以nums[i]为结尾元素的当前最大值maxCur之外,还需要维护一个以nums[i]为结尾元素的当前最小值minCur来解决负负得正的问题。而对于每一步中maxCur的更新过程如下: m a x C u r [ i ] = M a x n u m s [ i ] , M a x ( m a x C u r [ i − 1 ] ∗ n u m s [ i ] , m i n C u r [ i − 1 ] ∗ n u m s [ i ] ) maxCur[i]=Max{nums[i],Max(maxCur[i-1]*nums[i],minCur[i-1]*nums[i])} maxCur[i]=Maxnums[i],Max(maxCur[i1]nums[i],minCur[i1]nums[i]),不难理解对于每一步的以nums[i]为结尾元素的最大值有三种情况可以产生①前一步的最大值乘以当前值②前一步的最小值乘以当前值(负负得正的情况)③只有当前值(比如maxCu[i-1]和minCur[i-1]均为负数,而nums[i]为正数时)。同理minCur的更新过程如下所示: m i n C u r [ i ] = M i n n u m s [ i ] , M i n ( m a x C u r [ i − 1 ] ∗ n u m s [ i ] , m i n C u r [ i − 1 ] ∗ n u m s [ i ] ) minCur[i]=Min{nums[i],Min(maxCur[i-1]*nums[i],minCur[i-1]*nums[i])} minCur[i]=Minnums[i],Min(maxCur[i1]nums[i],minCur[i1]nums[i])
对于所给的测试用例nums=[2,3,-2,4]的求解过程如下所示

求解maxCurminCurresult
step0222
step1636
step2-2-126
step34-486

3、代码实现(java)
这里由于我们每一步只需要用到上一步的极小值以及极大值因此分别各只用一个变量进行存储即可。

class Solution {
    public int maxProduct(int[] nums) {
            int minCur = nums[0];
            int maxCur = nums[0];
            int result = nums[0];
            for(int i=1;i<nums.length;i++){
                int  tmp = maxCur;
                maxCur = Math.max(Math.max(maxCur*nums[i],minCur*nums[i]),nums[i]);
                minCur = Math.min(Math.min(tmp*nums[i],minCur*nums[i]),nums[i]);
                result = Math.max(result,maxCur);
            }
            return result;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值