题目链接: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. json 当集合类型的字符串变成集合时候 里面有map类型的转换操作

  2. 当使用listIterator进行迭代时候 list的迭代器可以在创建迭代器对象后 添加数据 但打印的时候不显示添加后的数据。 collection 的iterator迭代器不能添加数据 。list的对象与collection的实例对象都不能在创建迭代器后添加数据 list的迭代器保存的是循环前的数据长度

  3. hdu3507 Print Article(斜率优化入门)(pascal)

    Problem Description Zero has an old printer that doesn't work well sometimes. As it is antique, he s ...

  4. c# partial使用

    1.有2个类   class1.cs  ,class2.cs 2.这2个类里面都可以定义成这样 public partial class ClassAll { } 3.结果,里面的方法都是共享的,就像 ...

  5. 【Treeview】遍历本地磁盘

    一.前言 Treeview控件常用于遍历本地文件信息,通常与Datagridview与ImageList搭配.ImageList控件用于提供小图片给TreeView控件,DatagridView通常显 ...

  6. 【BZOJ3667】Rabin-Miller算法(Pollard_rho)

    [BZOJ3667]Rabin-Miller算法(Pollard_rho) 题面 呜,权限题,别问我是怎么做的(我肯定没有权限号啊) 第一行:CAS,代表数据组数(不大于350),以下CAS行,每行一 ...

  7. VK Cup 2017 Round 3 + Codeforces Round #412

    A 读题题 B 就是你排名第p,得了x分,而最终至少需要y分,你需要最少的successful hack,使得最终得分s>=y,且由s随机取25个数,使p被选中. (1)暴力枚举hack成功几次 ...

  8. Codeforces 578B. "Or" Game(思维题)

    我们知道所有sigma(2^i){i<n}比2^n小,所以我们肯定是把这k次操作全部丢到一个数上看看能不能凑出二进制下一个更高位的1. 因为k最大只有10,我们可以求出每一个数乘以k次之后的值, ...

  9. isnotblank与isnotempty的区别

  10. 「Python」人脸识别应用

    人脸识别主要步骤: face_recognition 库的安装 安装此库,首先需要安装编译dlib,此处我们偷个懒,安装软件Anaconda(大牛绕过),此软件预装了dlib. 安装好后,我们直接通过 ...