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

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

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

  1. public int maxProduct(int[] nums) {
  2. int res = Integer.MIN_VALUE, len = nums.length;
  3. for(int i = 0; i < len; i++) {
  4. int sum = 1;
  5. for(int j = i; j < len; j++) {
  6. sum *= nums[j];
  7. res = Math.max(res, sum);
  8. }
  9. }
  10. return res;
  11. }

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

  1. public int maxProduct(int[] nums) {
  2. int dp_max[] = new int[nums.length];
  3. int dp_min[] = new int[nums.length];
  4. int res = Integer.MIN_VALUE;
  5. dp_max[0] = nums[0];
  6. dp_min[0] = nums[0];
  7. for(int i = 1; i < nums.length; i++) {
  8. //更新最大值数组
  9. dp_max[i] = Math.max(Math.max(dp_max[i - 1] * nums[i], dp_min[i - 1] * nums[i]), nums[i]);
  10. //更新最小值数组
  11. dp_min[i] = Math.min(Math.min(dp_max[i - 1] * nums[i], dp_min[i - 1] * nums[i]), nums[i]);
  12. res = Math.max(dp_max[i], res);
  13. }
  14. return res;
  15. }

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

  1. public int maxProduct(int[] nums) {
  2. int res = Integer.MIN_VALUE, sum = 1;
  3. //正向遍历,取最大值
  4. for(int i = 0; i < nums.length; i++) {
  5. sum *= nums[i];
  6. res = Math.max(res, sum);
  7. if(nums[i] == 0) {
  8. sum = 1;
  9. }
  10. }
  11. //反向遍历,取最大值
  12. sum = 1;
  13. for(int i = nums.length - 1; i >= 0; i--) {
  14. sum *= nums[i];
  15. res = Math.max(res, sum);
  16. if(nums[i] == 0) {
  17. sum = 1;
  18. }
  19. }
  20. return res;
  21. }

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

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

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

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

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

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

  1. public int maxProduct(int[] nums) {
  2. int res = nums[0], ma = nums[0], mi = nums[0];
  3. for(int i = 1; i < nums.length; i++) {
  4. if(nums[i] <= 0) {
  5. int t = ma;
  6. ma = mi;
  7. mi = t;
  8. }
  9. ma = Math.max(ma * nums[i], nums[i]);
  10. mi = Math.min(mi * nums[i], nums[i]);
  11. res = Math.max(ma, res);
  12. }
  13. return res;
  14. }

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. HDU4472_Count

    题目的意思简单,给你n个点,每个点(除根节点)都有且只有一个父节点.现在问你这些节点关系组成的图有多少种情况满足同一层节点上每个点的后继节点数量相等. 很简单,对于n节点,直接枚举n-1的的所有约数情 ...

  2. 最大流Dinic算法模板(pascal)

    program rrr(input,output); const inf=; type pointer=^nodetype; nodetype=record t,c:longint; next,rev ...

  3. 【uoj#174】新年的破栈 贪心

    题目描述 给你一个长度为 $n$ 的序列和一个空的双端队列,每次进行3种操作种的一种: 1.将序列中编号最小的数加入到双端队列的队尾:2.从双端队列的队尾取出一个数:3.从双端队列的队头取出一个数. ...

  4. 二分图匹配模板(dfs+bfs)

    dfs版: bool dfs(int u) { for(int i = head[u]; ~i; i = e[i].next) { int v = e[i].v; if(!vis[v]) { vis[ ...

  5. 【BZOJ1565】【NOI2009】植物大战僵尸(网络流)

    [BZOJ1565][NOI2009]植物大战僵尸(网络流) 题面 BZOJ 洛谷 题解 做了这么多神仙题,终于有一道能够凭借自己智商能够想出来的题目了.... 好感动. 这就是一个比较裸的最小割模型 ...

  6. 关于kali linux系统的简单工具

    Linux系统中关于几个重要目录的原英文解释: /etc/: Contains configuration files of the installed tools /opt/: Contains M ...

  7. Linux系统启动详解(二)

    上节讲到了Linux启动大体流程,及grub的作用,本节主要扯扯initramfs的那些事,并且通过简单修改initramfs,将整体操作系统运行到了内存中. 3       initramfs 3. ...

  8. Mac 开发装机必备

    ==============设置=========================== Mac 启动台图标大小调整 1.终端运行命令:10代表一行显示10个图标,几个可以自定义 defaults wr ...

  9. LAMP安全加固

    LAMP安全: 1.BIOS:设置BIOS密码,禁用从CD-ROM和软盘引导 2.SSH安全:修改/etc/ssh/sshd_configPermitRootLogin = no //禁止root访问 ...

  10. 斯皮尔曼等级相关(Spearman’s correlation coefficient for ranked data)

    sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...