2020-05-18 LeetCode 152 乘积最大子数组 c

9 篇文章 0 订阅

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

示例1:

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

示例2:

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

 电脑终于修好了,niiiiiiice

 这道题一开始是没有任何思路的,然后去把相关题目"最大子序和"、“除自身意外的数组的乘积”、”打家劫舍“、”三个数的最大乘积“分别做了一遍,饶了一圈回来感觉这就是道动态规划题,和”53 最大子序和“很像,难点就是方程建立时负数的处理上。最大子序和如果f[i-1]小于0可以直接扔掉,因为对结果是负增益;但是对于这道题来说,如果f[i-1]小于零,在后续遍历中乘以一个负数是可以变成正数的,因此如果更新的时候单纯取当前最大值可能会陷入局部最优,比如[2,-4,8,-1]中,最大值策略输出会是8,但是真正结果应该是64。

 联系到”628 三个数的最大乘积“的官方题解2,想到可以维护三个值,分别记录当前连续乘积最大值( f m i n f_{min} fmin)、连续乘积最小值( f m a x f_{max} fmax)和最终结果(answer),更新规则如下:
f m i n [ i ] = m i n [ f m i n [ i − 1 ] ∗ n i , f m a x [ i − 1 ] ∗ n i , n i ] f m a x [ i ] = m a x [ f m a x [ i − 1 ] ∗ n i , f m a x [ i − 1 ] ∗ n i , n i ] a n s w e r = m a x [ a n s w e r , f m a x [ i ] ] f_{min}[i]=min[f_{min}[i-1]*n_i,f_{max}[i-1]*n_i,n_i] \\ f_{max}[i]=max[f_{max}[i-1]*n_i,f_{max}[i-1]*n_i,n_i] \\ answer=max[answer,f_{max}[i]] fmin[i]=min[fmin[i1]ni,fmax[i1]ni,ni]fmax[i]=max[fmax[i1]ni,fmax[i1]ni,ni]answer=max[answer,fmax[i]]
 其中n就是nums[i],把最小值(一般是负数)和最大值分别记录,也就是记录两个绝对值最大的,这样更新的话就可以避免上面说的局部最优,最终返回answer即可。

代码实现:

#define max3(a,b,c) (a>b?a:b)>c?(a>b?a:b):c
#define min3(a,b,c) (a<b?a:b)<c?(a<b?a:b):c
#define max(a,b)  a>b?a:b

int maxProduct(int* nums, int numsSize){
    int minAns=nums[0],maxAns=nums[0],ans=nums[0];
    int i;
    for(i=1;i<numsSize;i++){
        int tmp=minAns;
        minAns=min3(minAns*nums[i],maxAns*nums[i],nums[i]);
        maxAns=max3(maxAns*nums[i],tmp*nums[i],nums[i]);
        ans=max(ans,maxAns);
    }
    return ans;
}

 这里有一个细节就是对minAns和maxAns更新时,先更新的那一个必须先保存原来的值,否则更新规则会错误,以代码中为例,如果不用tmp保存minAns,更新规则就是,
f m i n [ i ] = m i n [ f m i n [ i − 1 ] ∗ n i , f m a x [ i − 1 ] ∗ n i , n i ] f m a x [ i ] = m a x [ f m i n [ i ] ∗ n i , f m a x [ i − 1 ] ∗ n i , n i ] a n s w e r = m a x [ a n s w e r , f m a x [ i ] ] f_{min}[i]=min[f_{min}[i-1]*n_i,f_{max}[i-1]*n_i,n_i] \\f_{max}[i]=max[f_{min}[i]*n_i,f_{max}[i-1]*n_i,n_i] \\answer=max[answer,f_{max}[i]] fmin[i]=min[fmin[i1]ni,fmax[i1]ni,ni]fmax[i]=max[fmin[i]ni,fmax[i1]ni,ni]answer=max[answer,fmax[i]]
f m a x f_{max} fmax的更新显然是不对的

运行结果:
2020-05-18_114841

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值