LeetCode——152. Maximum Product Subarray

问题描述:

Find the contiguous subarray within an array (containing at least one number) which has the largest product.

For example, given the array [2,3,-2,4],
the contiguous subarray [2,3] has the largest product = 6.

  题目大致的意思是给你一个数组,要你算连续的子数组乘积的最大值。
  一开始看到这道题,很容易就想到暴力拆解的方法,但是说实话,这样子处理起来时间复杂度很高,肯定是不行的。再仔细想想,就想到了动态规划的想法了。很明显在这种数组中求子数组求和或者求积的最大值的题中,肯定是要有个变量来保存最大值,以及有其他变量来在遍历的过程中保存中间值的,这道题就是一个很经典的例子。
  数组中只有整数,那就是负整数、正整数还有0三种。如果对数组进行遍历,会遇到这三种数,就对应三种情况吧:
  ①正整数:正整数×正整数=更大的正整数,而正整数×负整数=更小的负整数这个没问题。
  ②负整数:负整数×正整数=更小的负整数,而负整数×负整数=更大的正整数。负整数的存在,就意味着我们不可能只需要一个max的中间变量就搞定,而需要一个min,因为无论如何,min×负整数肯定是大于max×正整数的(先排除0的情况),所以我们需要两个中间变量:max、min。
  ③0:呃,0的出现,让情况变得复杂了许多。无论你min或max是什么,最后×0一定是0,那么如果你后面遍历时还把后面的元素算进前面这个子数组时,已经没有什么意义了,乘积一直都是0。因此,0应该是作为两个子数组间的分界元素,那么我们就要使用一个result来保存中间变量的最大值,最后是要作为返回值返回的。此外,在开始下一个子数组的计算时,前面的max和min肯定是要设为下一个子数组的首元素的,那么这里要怎么处理呢?想一想······
  其实很简单,我们只要保存这个0,然后留到下一个开始元素,与开始元素进行比较,那么max和min就可以设为我们想要的首元素的值了。因此,我们的比较表达式是:

 max = Math.max(nums[i], nums[i]*max 或者 nums[i]*min)
 min = Math.min(nums[i], nums[i]*min 或者 nums[i]*max) 

  解释一下:如果nums[i]是一个非0的数,那么取max或者取min一定是取后面的这个表达式的值;而如果nums[i]是0,那么max和min肯定被置0,在下一步与下一个子数组的首元素进行比较时,就可以将这个首元素赋到max或者min中去。
  下面是代码:

    public int maxProduct(int[] nums) {
        int max = nums[0];
        int min = nums[0];
        int result = nums[0];
        for(int i = 1; i < nums.length; i++) {
            int temp = nums[i];
            if(temp < 0) {
                int tempMin = min;
                min = Math.min(temp, temp*max);
                max = Math.max(temp, temp*tempMin);
            }
            if(temp >= 0) {
                max = Math.max(temp, temp*max);
                min = Math.min(temp, temp*min);
            }
            result = Math.max(result, max);
        }
        return result;
    }

  总的来说,这道题的核心就是动态规划,要想到使用max和min来保存中间值,然后根据max和result的值来更新所需要的最大值;其次就是在遇到正整数、负整数、0三种情况时分别判断,并做出一个总的处理方法,这道题就可以解决了。
  谢谢大家观看我的博客。如果有不明白的地方,或者是文中有错误的地方,欢迎指出,谢谢!如果大家喜欢我的博客,也可以给我点点赞。你们的点赞就是我的动力!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值