题目:

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

152. Maximum Product Subarray的更多相关文章

  1. leetcode 53. Maximum Subarray 、152. Maximum Product Subarray

    53. Maximum Subarray 之前的值小于0就不加了.dp[i]表示以i结尾当前的最大和,所以需要用一个变量保存最大值. 动态规划的方法: class Solution { public: ...

  2. 152. Maximum Product Subarray - LeetCode

    Question 152. Maximum Product Subarray Solution 题目大意:求数列中连续子序列的最大连乘积 思路:动态规划实现,现在动态规划理解的还不透,照着公式往上套的 ...

  3. 求连续最大子序列积 - leetcode. 152 Maximum Product Subarray

    题目链接:Maximum Product Subarray solutions同步在github 题目很简单,给一个数组,求一个连续的子数组,使得数组元素之积最大.这是求连续最大子序列和的加强版,我们 ...

  4. 【刷题-LeetCode】152 Maximum Product Subarray

    Maximum Product Subarray Given an integer array nums, find the contiguous subarray within an array ( ...

  5. [LeetCode] 152. Maximum Product Subarray 求最大子数组乘积

    Given an integer array nums, find the contiguous subarray within an array (containing at least one n ...

  6. [LeetCode]152. Maximum Product Subarray

    This a task that asks u to compute the maximum product from a continue subarray. However, you need t ...

  7. LeetCode 152. Maximum Product Subarray (最大乘积子数组)

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

  8. 152. Maximum Product Subarray (Array; DP)

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

  9. Java for LeetCode 152 Maximum Product Subarray

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

  10. leetcode 152. Maximum Product Subarray --------- java

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

随机推荐

  1. VS2015+AngularJS+Ionic开发

    安装VS2015 Update2的过程是非常曲折的.还好经过不懈的努力,终于折腾成功了. 如果开发Cordova项目的话,推荐大家用一下ionic这个框架,效果还不错.对于Cordova.PhoneG ...

  2. 【转】JavaScript系列文章:自动类型转换

    我们都知道,JavaScript是类型松散型语言,在声明一个变量时,我们是无法明确声明其类型的,变量的类型是根据其实际值来决定的,而且在运行期间,我们可以随时改变这个变量的值和类型,另外,变量在运行期 ...

  3. 项目开发中常用到的SQL语句

    阅读目录 循环示例 循环示例 循环示例 循环示例 1.循环示例 在前端面试中最常见的问题就是页面优化和缓存(貌似也是页面优化),被问了几次后心虚的不行,平然平时多少会用到一些,但突然问我,很难把自己知 ...

  4. CPrintDialog

    CPrintDialog 封装windows为打印提供服务的通用窗体. BOOL GetDefaults(); //获取默认设备,不显示对话框 // Helpers for parsing infor ...

  5. WCF与Web API 区别(应用场景)

    Web api  主要功能: 支持基于Http verb (GET, POST, PUT, DELETE)的CRUD (create, retrieve, update, delete)操作 请求的回 ...

  6. FlashBuilder启动时一闪而过

    晚上的时候把项目目录直接剪切走了 早晨就打不开了 去workspace看log  .\workspace\.metadata\.log 发现如下代码!MESSAGE Could not read me ...

  7. mongodb 数据备份,还原笔记

    公司数据库迁移,所以补充了一下知识: 1 集合的导入和导出 命令行帮助 mongoexport --help  导出 导出 newsServer 数据库下  news 集合 mongoexport - ...

  8. IO流06_处理流

    [处理流] 处理流可以隐藏底层设备上节点流的差异,并对外提供更加方便的输入/输出的方法. 使用处理流的思路: 使用处理流来包装节点流,程序通过处理流来执行输入输出功能,让节点流与底层的I/O设备.文件 ...

  9. HDU 4430 Yukari's Birthday(二分)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4430 题目大意:给定n个蜡烛,围绕蛋糕的中心插同心圆,从里往外分别是第1圈.第2圈....第r圈,第 ...

  10. win2008 r2 远程桌面问题

    今天去机房给三台服务器上架,装了2008 R2系统,客户要求从外面通过公网IP能够访问服务器桌面,三台服务器都安装了远程协助的功能,结果有两台能正常访问,另外一台始终连不上,不知道哪个地方设置有问题, ...