题目链接:https://leetcode.com/problems/maximum-product-subarray/description/

题目大意:给出一串数组,找出连续子数组中乘积最大的子数组的乘积。

法一:暴力。竟然能过,数据也太水了。两个for循环,遍历每一个可能的连续子数组,找出最大值。代码如下(耗时161ms):

     public int maxProduct(int[] nums) {
int res = Integer.MIN_VALUE, len = nums.length;
for(int i = 0; i < len; i++) {
int sum = 1;
for(int j = i; j < len; j++) {
sum *= nums[j];
res = Math.max(res, sum);
}
}
return res;
}

法二(借鉴):dp,利用两个dp数组,dp_max[i]表示从0到i的数中,子数组乘积最大值,dp_min[i]表示从0到i的数中,子数组乘积最小值,然后每次都更新这两个值,从dp_max数组中取的最大值即可。代码如下(耗时4ms):

     public int maxProduct(int[] nums) {
int dp_max[] = new int[nums.length];
int dp_min[] = new int[nums.length];
int res = Integer.MIN_VALUE;
dp_max[0] = nums[0];
dp_min[0] = nums[0];
for(int i = 1; i < nums.length; i++) {
//更新最大值数组
dp_max[i] = Math.max(Math.max(dp_max[i - 1] * nums[i], dp_min[i - 1] * nums[i]), nums[i]);
//更新最小值数组
dp_min[i] = Math.min(Math.min(dp_max[i - 1] * nums[i], dp_min[i - 1] * nums[i]), nums[i]);
res = Math.max(dp_max[i], res);
}
return res;
}

法三(借鉴):两次遍历,正向遍历+反向遍历,空间复杂度是o(1),遇0则归1,否则尽管相乘,找到最大值。代码如下(耗时1ms);

     public int maxProduct(int[] nums) {
int res = Integer.MIN_VALUE, sum = 1;
//正向遍历,取最大值
for(int i = 0; i < nums.length; i++) {
sum *= nums[i];
res = Math.max(res, sum);
if(nums[i] == 0) {
sum = 1;
}
}
//反向遍历,取最大值
sum = 1;
for(int i = nums.length - 1; i >= 0; i--) {
sum *= nums[i];
res = Math.max(res, sum);
if(nums[i] == 0) {
sum = 1;
}
}
return res;
}

法四(借鉴):下面这种方法也是用两个变量来表示当前最大值和最小值的,但是没有无脑比较三个数,而是对于当前的nums[i]值进行了正负情况的讨论:

1. 当遍历到一个正数时,此时的最大值等于之前的最大值乘以这个正数和当前正数中的较大值,此时的最小值等于之前的最小值乘以这个正数和当前正数中的较小值。

2. 当遍历到一个负数或0时,我们先用一个变量t保存之前的最大值mx,然后此时的最大值等于之前最小值乘以这个负数和当前负数中的较大值,此时的最小值等于之前保存的最大值t乘以这个负数和当前负数中的较小值。

3. 在每遍历完一个数时,都要更新最终的最大值。

P.S. 如果这里改成求最小值的话,就是求最小子数组乘积。代码如下(耗时3ms):
     public int maxProduct(int[] nums) {
int res = nums[0], ma = nums[0], mi = nums[0];
for(int i = 1; i < nums.length; i++) {
if(nums[i] > 0) {
ma = Math.max(ma * nums[i], nums[i]);
mi = Math.min(mi * nums[i], nums[i]);
}
//注意负数或0的情况
else {
int t = ma;
ma = Math.max(mi * nums[i], nums[i]);
mi = Math.min(t * nums[i], nums[i]);
}
res = Math.max(res, ma);
}
return res;
}

法五(借鉴):在上面的解法中我们分析了当nums[i]为正数时,最大值和最小值的更新情况,为负数时,稍有不同的就是最小值更新时要用到之前的最大值,而不是更新后的最大值,所以我们才要用变量t来保存之前的结果。而下面这种方法的巧妙处在于先判断一个当前数字是否是负数,是的话就交换最大值和最小值。那么此时的mx就是之前的mn,所以mx的更新还是跟上面的方法是统一的,而在在更新mn的时候,之前的mx已经保存到mn中了,而且并没有改变,所以可以直接拿来用。代码如下(耗时1ms):

     public int maxProduct(int[] nums) {
int res = nums[0], ma = nums[0], mi = nums[0];
for(int i = 1; i < nums.length; i++) {
if(nums[i] <= 0) {
int t = ma;
ma = mi;
mi = t;
}
ma = Math.max(ma * nums[i], nums[i]);
mi = Math.min(mi * nums[i], nums[i]);
res = Math.max(ma, res);
}
return res;
}

152.Maximum Product Subarray---dp---连续子数组的最大乘积---《编程之美》2.13子数组的最大乘积的更多相关文章

  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】Maximum Product Subarray 求连续子数组使其乘积最大

    Add Date 2014-09-23 Maximum Product Subarray Find the contiguous subarray within an array (containin ...

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

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

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

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

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

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

  7. [LeetCode]152. Maximum Product Subarray

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

  8. LeetCode OJ 152. Maximum Product Subarray

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

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

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

  10. 152. Maximum Product Subarray最大乘积子数组/是否连续

    [抄题]: Given an integer array nums, find the contiguous subarray within an array (containing at least ...

随机推荐

  1. 【JavaScript】JAVA-js中比较日期大小

    业务场景:js中根据yyyy-MM-dd格式的日期进行比较来动态显示相关图标的出现与否 var DS173305 = { DS173305Grid: null, initDataGrid: funct ...

  2. Redis windows环境安装 以及 redis整合spring

    Redis对于Linux是官方支持的,安装和使用没有什么好说的,普通使用按照官方指导,5分钟以内就能搞定.详情请参考: http://redis.io/download Redis官方是不支持wind ...

  3. C++11线程使用总结

    std::thread 在 <thread> 头文件中声明,因此使用 std::thread 需包含 <thread> 头文件. <thread> 头文件摘要 &l ...

  4. 【TopCoder10697】RabbitNumbering

    [TopCoder10697]RabbitNumbering 题面 Vjudge 给定\(n\)个数,每个数的范围是\([1,ai]\),求所有数都不同的方案数. 题解 把这个直接当做一个套路来用 对 ...

  5. Last Position of Target

    For a given sorted array (ascending order) and a target number, find the first index of this number ...

  6. 函数式编程(1)-高阶变成(1)-map/reduce

    map/reduce Python内建了map()和reduce()函数. 如果你读过Google的那篇大名鼎鼎的论文“MapReduce: Simplified Data Processing on ...

  7. javascript中的位运算,

    罗浮宫群里又有讨论位运算符号|了,做过一段时间php,数据库保存布尔值数据经常用到,比如100110 就表明了六个属性的是与否,极大减少了数据量..] ECMAScript 中位运算跟其他语言一样的. ...

  8. vs下取得资源文件中的版本信息

    在Windows Mobile和Wince(Windows Embedded CE)下开发的产品,有时候需要显示当前产品的版本信息.一般来说,版本信息是保存在资源文件里面的,例如下图: 为了保持一致, ...

  9. kotlin 变量声明

    Kotlin 是强类型的语言,Kotlin 要求所有的变量必须先声明.后使用,声明变量时必须显示或隐式指定变量的类型(隐式的是指,声明的时候同时初始化,这样编译的时候就可以推断出该变量的类型了,Jav ...

  10. apk签名验证机制

    声明: 1.本帖转载自:http://riusksk.blogbus.com/logs/272154406.html,仅供自用,勿喷 2.欢迎交流学习 签名后的APK,在/META-INF目录下会生成 ...