题目链接: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. bzoj1853-大包子的幸运数字

    题意 称只含有 6 和 8 的数字为幸运数字.称幸运数字的倍数为类幸运数字.求 \([l,r]\) 中有多少个类幸运数字.\(1\le l,r\le 10^{10}\) . 分析 幸运数字最多有 \( ...

  3. 51nod 1624 取余最短路(set)

    题意: 佳佳有一个n*m的带权矩阵,她想从(1,1)出发走到(n,m)且只能往右往下移动,她能得到的娱乐值为所经过的位置的权的总和. 有一天,她被下了恶毒的诅咒,这个诅咒的作用是将她的娱乐值变为对p取 ...

  4. 【bzoj2257】[Jsoi2009]瓶子和燃料 扩展裴蜀定理+STL-map

    题目描述 给出 $n$ 个瓶子和无限的水,每个瓶子有一定的容量.每次你可以将一个瓶子装满水,或将A瓶子内的水倒入B瓶子中直到A倒空或B倒满.从中选出 $k$ 个瓶子,使得能够通过这 $k$ 个瓶子凑出 ...

  5. Android四大组件之Service(续)

    本地服务启动和通过广播的方式回调是非常简单的. 下面介绍远程服务和通过远程回调的方式通知activity的方式. 1.service定义: package com.joyfulmath.globals ...

  6. 转发---[沧海拾遗]java并发之CountDownLatch、Semaphore和CyclicBarrier

    JAVA并发包中有三个类用于同步一批线程的行为,分别是CountDownLatch.Semaphore和CyclicBarrier. CountDownLatch CountDownLatch是一个计 ...

  7. Django对应的路由名称

    1. 名字很长,修改起来很麻烦 2.Django提供了一种方法 在urls.py中修改了名字以后,html中会自动对应做修改.这样提交表单的时候就会比较方便了.跳转到写死的某个URL. 3.根据名字i ...

  8. 小Z的袜子 题解报告【莫队】

    Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命-- 具体来说,小Z把这N只 ...

  9. AndroidManifest.xml 权限 中英对照表

    声明: 1.本文转载自:http://www.52pojie.cn/thread-304613-1-1.html 2.如有转载请复制上面连接声明,尊重原创 常用权限对照表 android.permis ...

  10. [DeeplearningAI笔记]卷积神经网络2.5-2.7 Network in Network/1*1卷积/Inception网络/GoogleNet

    4.2深度卷积网络 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 Inception网络 --Szegedy C, Liu W, Jia Y, et al. Going deepe ...