题目:

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. SQL Server2008数据库自动备份步骤

    一,  在电脑开始菜单中选择“SQL Server Management Studio”双击.在出现的界面中点击“连接”按钮. 二,  在出现的“ Microsoft SQL Server Manag ...

  2. iOS启动图片适配问题

    Portrait 是竖屏 top home button Landscape是横屏 left home button retina 要求640x1136pixels, 在右边的Image属性 Expe ...

  3. 理解css 中的position五个属性

    在实际开发页面布局时,运用position,对定位的块级元素的嵌套的效果总是不太理解,这里做了几个测试 一般的在w3c中我们可以很容易的获取定义: static : 默认值.没有定位,元素出现在正常的 ...

  4. UVA - 297 Quadtrees (四分树)

    题意:求两棵四分树合并之后黑色像素的个数. 分析:边建树边统计. #include<cstdio> #include<cstring> #include<cstdlib& ...

  5. 网络编程之UDP协议

    UDP协议 UDP(User Datagram Protocol)也就是用户数据报协议,是一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETF RFC 768是UDP的正式规范. 提 ...

  6. DataList和Repeater

    DataList和Repeater是两个十分有用的控件,在新闻列表和图片展示的地方经常用到.在这里简单的把他们介绍一下. 1.DataList: 前端页面: <asp:DataList ID=& ...

  7. Asp.net 图片文件防盗链介绍

    想要实现文件放盗链的功能 首先添加一个全局文件 Global.asax 在 Application_BeginRequest中我们可以判断Http报文头中的UrlReferre是否来源本站. if ( ...

  8. 今日吐槽20151208.net服务器控件

    正文 今天有个小任务是给页面添加一个搜索条件,复选框多选.因为页面都是服务器控件,我也只能用服务器控件配合了.然后给页面加了一个  CheckBoxList  控件.后台通过数据表加载数据. fore ...

  9. MySQL基础学习之开始

    学习MySQL数据库几个月了,从什么都不懂到现在这个地步,说实话感触很大,也感觉自己有许多不足之处.当接触MySQL的时候, 连创建一个数据表都想了很长的时间,不知道许多东西.幸亏我有一个好的老师,她 ...

  10. [转]LoadRunner脚本录制常见问题整理

    LoadRunner脚本录制常见问题整理 1.LoadRunner录制脚本时为什么不弹出IE浏览器? 当一台主机上安装多个浏览器时,LoadRunner录制脚本经常遇到不能打开浏览器的情况,可以用下面 ...