zoukankan      html  css  js  c++  java
  • 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.

    链接: http://leetcode.com/problems/maximum-product-subarray/

    题解:

    求最大乘积子数组。 依然是用Dynamic Programming的思想,不过这回我们要维护一个max以及一个min。根据nums[i]的符号来决定应该怎样计算就可以了。 

    Time Complexity - O(n), Space Complexity - O(1)。

    public class Solution {
        public int maxProduct(int[] nums) {
            if(nums == null || nums.length == 0)
                return 0;
            int res = nums[0], max = nums[0], min = nums[0];
            
            for(int i = 1; i < nums.length; i++) {
                if(nums[i] > 0) {
                    max = Math.max(nums[i], nums[i] * max);
                    min = Math.min(nums[i], nums[i] * min);
                } else {
                    int max_copy = max;
                    max = Math.max(nums[i], nums[i] * min);
                    min = Math.min(nums[i], nums[i] * max_copy);
                }
                res = Math.max(res,max);
            }
            
            return res;
        }
    }

    二刷:

    一刷肯定没好好做,直接拷贝答案了吧....导致如今没什么大印象。

    下面代码写得比较糙,没有加上overflow和underflow的处理。

    1. 这里我们对这道题目,先创建一个global max = Integer.MIN_VALUE,一个保存当前正数最大值的posMax = 1和一个保存当前负数最小值的negMax = 1。
    2. 接下来我们开始从0遍历数组。主要考虑三种情况, 当前num 大于,小于,等于 0。
      1. 当num > 0的时候,我们直接将posMax和negMax与 num相乘,然后尝试更新max
      2. 当num < 0的时候,我们先设置一个tmp = posMax。
        1. 在当前negMax < 0的时候
          1. 我们可以更新posMax = negMax * max, 负负得正
          2. 更新negMax = tmp * num, 即negMax为之前的posMax * num
          3. 尝试更新max = Math.max(max, posMax)
        2. 否则negMax > 0
          1. 因为num是负数,所有我们更新posMax = 1
          2. 更新negMax *= num
          3. 尝试更新 max = Math.max(max, num), 即max跟当前数字进行比较
      3. 当num == 0的时候,这时候之前cache的乘积都断了
        1. 我们更新posMax = 1,  negMax = 1
        2. 尝试更新 max = Math.max(max, num)。  即max跟当前数字比较, 因为当前数字num = 0,所以也可以直接写 Math.max(max, 0)。
    3. 返回结果max。

    写得比较繁杂,应该可以简化不少。留给下一次了。  参观了一下Discuss区,大神们写得好棒好巧妙...收录在reference里。 下回再写的时候要参考写出简单的代码。

    Java:

    public class Solution {
        public int maxProduct(int[] nums) {
            if (nums == null || nums.length == 0) return 0;
            int max = Integer.MIN_VALUE;
            int posMax = 1, negMax = 1;
            for (int num : nums) {
                if (num > 0) {
                    posMax *= num;
                    negMax *= num;
                    max = Math.max(max, posMax);
                } else if (num < 0) {
                    if (negMax < 0) {
                        int tmp = posMax;
                        posMax = negMax * num;
                        negMax = tmp * num;
                        max = Math.max(max, posMax);
                    } else {
                        posMax = 1;
                        negMax *= num;
                        max = Math.max(max, num);
                    }
                } else {
                    posMax = 1;
                    negMax = 1;
                    max = Math.max(max, num);
                }
            }
            return max;
        }
    }

     

    来自mzchen大神的swap做法,好巧妙:

    这里我们跟上面一样维护一个min和一个max,以及一个global的结果res。每次当nums[i] < 0的时候,我们swap一下min和max。在一般情况下,我们更新

    max = Math.max(nums[i], max * nums[i]), min = Math.min(nums[i], min * nums[i]),这两个步骤可以处理nums[i] = 0的case。最后我们尝试更新res = Math.max(res, max)。 

    Java:

    public class Solution {
        public int maxProduct(int[] nums) {
            if (nums == null || nums.length == 0) return 0;
            int res = nums[0];
            int max = nums[0], min = nums[0];
            for (int i = 1; i < nums.length; i++) {
                if (nums[i] < 0) {
                    int tmp = max;
                    max = min;
                    min = tmp;
                }
                max = Math.max(nums[i], max * nums[i]);
                min = Math.min(nums[i], min * nums[i]);
                res = Math.max(res, max);
            }
            return res;
        }
    }

    Update:

    public class Solution {
        public int maxProduct(int[] nums) {
            if (nums == null || nums.length == 0) return 0;
            int max = 1, min = 1;
            int res = Integer.MIN_VALUE;
            for (int num : nums) {
                if (num < 0) {
                    int tmp = max;
                    max = min;
                    min = tmp;
                } 
                max = Math.max(num, max * num);
                min = Math.min(num, min * num);
                res = Math.max(res, max);
            }
            return res;
        }
    }

    Test cases:

    [-5, 2, -1, -7]

    [-1, 2, 3, -4]

    [-5, 2, 0, -1, -7]

    [-1, -2, -3, -4]

    [0, -5, -2, -1, 7]

    [-2]

    [2]

    [-2, -2, -2, -2]

    [Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE]    <- 这个没有测

    Reference:

    https://leetcode.com/discuss/11923/sharing-my-solution-o-1-space-o-n-running-time

    https://leetcode.com/discuss/14235/possibly-simplest-solution-with-o-n-time-complexity

    https://leetcode.com/discuss/19795/share-my-c-solution-maybe-is-the-simplest-solution

    https://leetcode.com/discuss/16238/simple-java-code

    https://leetcode.com/discuss/64079/my-concise-dp-o-n-java-solution-with-o-1-extra-space

  • 相关阅读:
    20201220第二周学习总结
    师生关系
    快速浏览教材
    学期2020-2021-1学号20201220《信息安全专业导论》第1周学习总结
    编程将字符串s倒序输出,要求利用函数递归实现
    小学生四则运算随机生成程序
    礼炮问题
    C语言最大公约数
    C语言判断三角形类型
    C语言:一元二次方程解的所有情况
  • 原文地址:https://www.cnblogs.com/yrbbest/p/4489668.html
Copyright © 2011-2022 走看看