题目链接: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. 【uoj#207】共价大爷游长沙 随机化+LCT维护子树信息

    题目描述 给出一棵树和一个点对集合S,多次改变这棵树的形态.在集合中加入或删除点对,或询问集合内的每组点对之间的路径是否都经过某条给定边. 输入 输入的第一行包含一个整数 id,表示测试数据编号,如第 ...

  2. BZOJ4923 K小值查询(splay)

    容易想到建一棵平衡树,修改时打上标记即可.但是修改会导致平衡树结构被破坏.注意到实际上只有[k+1,2k)这一部分数在平衡树中的位置会被改变,所以对这一部分暴力修改,因为每次都会使其至少减小一半,复杂 ...

  3. Cornfields POJ - 2019(二维RMQ板题)

    就是求子矩阵中最大值与最小值的差... 板子都套不对的人.... #include <iostream> #include <cstdio> #include <sstr ...

  4. word2013 如何套用模版

    文件-->选项-->加载项-->最下面下拉框选择“模版”-->点击转到

  5. hadoop(二)hadoop集群的搭建

    一.集群环境准备工作 1.修改主机名 在root 账户下 vi /etc/sysconfig/network   或者 sudo vi /etc/sysconfig/network 2.设置系统默认启 ...

  6. NOIP2017 Day2 T2 宝藏(状压DP)

    $O(n*3^n)$好难想...还有好多没见过的操作 令$f[i][j]$表示最深深度为i,点的状态为j的最小代价,每次枚举状态$S$后,计算$S$的补集里的每个点与S里的点的最小连边代价,再$O(3 ...

  7. 关于EMGU CV的那些事——1.环境搭建(win8 vs2012 emgucv3.0)

    http://blog.csdn.net/aptx704610875/article/details/46045689 楼主读研阶段研究图像处理,想用C#实现PTAM/PTAMM算法并用UNITY创建 ...

  8. SpringMVC 重定向

    在返回视图名字的字符串前面加forword:或redirect:前缀是就会对他们做特殊处理,它们分别是转发和重定向 我们测试一个重定向操作把 Java代码 @RequestMapping(" ...

  9. centos7 配置 yum 安装的 jdk

    yum 安装的 java,jdk 路径默认是 /usr/lib/jvm/java-* 我们修改 .bash_profile 文件加上下面几行: export JAVA_HOME=/usr/lib/jv ...

  10. 使用rabbitmq消息队列

    一.前言 在python中本身就是存在队列queue.一个是线程队列queue,另一个是进程multiprocessing中的队列Queue. 线程queue:只用于线程之间的数据交互 进程Queue ...