作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/


题目地址:https://leetcode.com/problems/maximum-product-subarray/description/

题目描述

Given an integer array nums, find the contiguous subarray within an array (containing at least one number) which has the largest product.

Example 1:

Input: [2,3,-2,4]
Output: 6
Explanation: [2,3] has the largest product 6.

Example 2:

Input: [-2,0,-1]
Output: 0
Explanation: The result cannot be 2, because [-2,-1] is not a subarray.

题目大意

求连续子数组最大乘积。

解题方法

双重循环

这个题最简单粗暴的方法当然是两重循环啦!遍历每个区间的开始和结束位置,然后求这个区间的积,然后保留最大的积即可。没想到C++直接提交竟然给通过了!说明这个O(N^2)的时间复杂度还是能够接受的。

class Solution {
public:
int maxProduct(vector<int>& nums) {
const int N = nums.size();
int res = INT_MIN;
for (int i = 0; i < N; ++i) {
int cur = 1;
for (int j = i; j < N; ++j) {
if (j == i)
cur = nums[i];
else
cur = cur * nums[j];
res = max(res, cur);
}
}
return res;
}
};

动态规划

如果是连续子数组的和的问题我们肯定能想到虫取法之类的,但是求积就比较麻烦了,因为某个位置可能出现了0或者负数。。当遇到0的时候,整个乘积会变成0;当遇到负数的时候,当前的最大乘积会变成最小乘积,最小乘积会变成最大乘积。

有上面的分析可以看出,必须使用两个数组分别记录以某个位置i结尾的时候的最大乘积和最小乘积了。令最大乘积为f,最小乘积为g。那么有:

  • 当前的最大值等于已知的最大值、最小值和当前值的乘积,当前值,这三个数的最大值。
  • 当前的最小值等于已知的最大值、最小值和当前值的乘积,当前值,这三个数的最小值。
  • 结果是最大值数组中的最大值。

时间复杂度是O(N),空间复杂度是O(N). N是数组大小。超过了87%的提交。

题外话:是不是和股票交易问题很像?

class Solution(object):
def maxProduct(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums: return 0
N = len(nums)
f = [0] * N
g = [0] * N
f[0] = g[0] = res = nums[0]
for i in range(1, N):
f[i] = max(f[i - 1] * nums[i], nums[i], g[i - 1] * nums[i])
g[i] = min(f[i - 1] * nums[i], nums[i], g[i - 1] * nums[i])
res = max(res, f[i])
return res

这个版本的C++代码如下:

class Solution {
public:
int maxProduct(vector<int>& nums) {
const int N = nums.size();
vector<int> mx(N);
vector<int> mn(N);
int res = mx[0] = mn[0] = nums[0];
for (int i = 1; i < N; ++i) {
mx[i] = max(nums[i], max(mx[i - 1] * nums[i], mn[i - 1] * nums[i]));
mn[i] = min(nums[i], min(mx[i - 1] * nums[i], mn[i - 1] * nums[i]));
res = max(mx[i], res);
}
return res;
}
};

上面的方法使用了数组实现,我们注意到,每次更新只用到了前面的一个值,所以可以使用变量优化空间复杂度。

class Solution(object):
def maxProduct(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums: return 0
N = len(nums)
f = g = res = nums[0]
for i in range(1, N):
pre_f, pre_g = f, g
f = max(pre_f * nums[i], nums[i], pre_g * nums[i])
g = min(pre_f * nums[i], nums[i], pre_g * nums[i])
res = max(res, f)
return res

时间复杂度是O(N),空间复杂度是O(1).N是数组大小。超过了99.9%的提交。

在上面两个做法中,使用求三个数最大、最小的方式来更新状态,确实很暴力。事实上可以使用判断,直接知道怎么优化。当nums[i]为正的时候,那么正常更新。如果nums[i]<=0的时候,需要反向更新。

class Solution(object):
def maxProduct(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums: return 0
N = len(nums)
f = g = res = nums[0]
for i in range(1, N):
if nums[i] > 0:
f, g = max(f * nums[i], nums[i]), min(g * nums[i], nums[i])
else:
f, g = max(g * nums[i], nums[i]), min(f * nums[i], nums[i])
res = max(res, f)
return res

时间复杂度是O(N),空间复杂度是O(1).N是数组大小。超过了47%的提交。

在上面的做法中可以看出来,两个更新公式里面f和g的位置是互换的,所以可以提前判断nums[i]的正负进行提前的互换。

class Solution(object):
def maxProduct(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums: return 0
N = len(nums)
f = g = res = nums[0]
for i in range(1, N):
if nums[i] < 0:
f, g = g, f
f, g = max(f * nums[i], nums[i]), min(g * nums[i], nums[i])
res = max(res, f)
return res

时间复杂度是O(N),空间复杂度是O(1).N是数组大小。超过了47%的提交。

参考资料

http://www.cnblogs.com/grandyang/p/4028713.html

日期

2018 年 10 月 20 日 —— 10月剩余的时间又不多了

【LeetCode】152. Maximum Product Subarray 解题报告(Python & C++)的更多相关文章

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

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

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

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

  3. Java for LeetCode 152 Maximum Product Subarray

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

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

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

  5. LeetCode Maximum Product Subarray 解题报告

    LeetCode 新题又更新了.求:最大子数组乘积. https://oj.leetcode.com/problems/maximum-product-subarray/ 题目分析:求一个数组,连续子 ...

  6. leetcode 152. Maximum Product Subarray --------- java

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

  7. C#解leetcode 152. Maximum Product Subarray

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

  8. [leetcode]152. Maximum Product Subarray最大乘积子数组

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

  9. Leetcode#152 Maximum Product Subarray

    原题地址 简单动态规划,跟最大子串和类似. 一维状态空间可以经过压缩变成常数空间. 代码: int maxProduct(int A[], int n) { ) ; ]; ]; ]; ; i > ...

随机推荐

  1. 【ThermoRawFileParser】质谱raw格式转换mgf

    众所周知,Proteowizard MSconvert用于质谱原始数据的格式转换,但主要平台是windows,要想在Linux上运行需要打Docker或Wine,对于普通用户来说还是很困难的,想想质谱 ...

  2. 59. Divide Two Integers

    Divide Two Integers My Submissions QuestionEditorial Solution Total Accepted: 66073 Total Submission ...

  3. session与cookie 浏览器关闭时的区别

    session与cookie 浏览器关闭时的区别 cookie是存储在本地,当cookie在浏览器关闭的时候,再次打开是否记录之前的值,这跟cookie的过期时间设置有关. 如果cookie的过期时间 ...

  4. 搭建简单的SpringCloud项目一:注册中心和公共层

    注:笔者在搭建途中其实遇见不少问题,统一放在后面的文章说明,现在的搭建是测试OK的. GitHub:https://github.com/ownzyuan/test-cloud 后续:搭建简单的Spr ...

  5. 多选项、多个选择项【c#】

    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="AddDataInfoCe ...

  6. 前端1 — HTML — 更新完毕

    1.首先来了解一个东西 -- W3C标准( 全称是:World Wide Web Consortium ) 万维网联盟(外语缩写:W3C)标准不是某一个标准,而是一系列标准的集合 -- 这个其实每天都 ...

  7. 「Spark从精通到重新入门(一)」Spark 中不可不知的动态优化

    前言 Apache Spark 自 2010 年面世,到现在已经发展为大数据批计算的首选引擎.而在 2020 年 6 月份发布的Spark 3.0 版本也是 Spark 有史以来最大的 Release ...

  8. 12. Fedora 中文乱码问题

    1. Rhythmbox(音乐播放器乱码) yum install python-mutagen mid3iconv -e GBK *.mp3 2. totem电影播放机播放列表乱码解决1).修改to ...

  9. Spark产生数据倾斜的原因以及解决办法

    Spark数据倾斜 产生原因 首先RDD的逻辑其实时表示一个对象集合.在物理执行期间,RDD会被分为一系列的分区,每个分区都是整个数据集的子集.当spark调度并运行任务的时候,Spark会为每一个分 ...

  10. Angular中怎样创建service服务来实现组件之间调用公共方法

    Angular组件之间不能互相调用方法,但是可以通过创建服务来实现公共方法的调用. 实现 创建服务命令 ng g service 服务路径/服务名 比如这里在app/services目录下创建stor ...