【LeetCode】152. Maximum Product Subarray 解题报告(Python & C++)
作者: 负雪明烛
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++)的更多相关文章
- 求连续最大子序列积 - leetcode. 152 Maximum Product Subarray
题目链接:Maximum Product Subarray solutions同步在github 题目很简单,给一个数组,求一个连续的子数组,使得数组元素之积最大.这是求连续最大子序列和的加强版,我们 ...
- [LeetCode] 152. Maximum Product Subarray 求最大子数组乘积
Given an integer array nums, find the contiguous subarray within an array (containing at least one n ...
- Java for LeetCode 152 Maximum Product Subarray
Find the contiguous subarray within an array (containing at least one number) which has the largest ...
- LeetCode 152. Maximum Product Subarray (最大乘积子数组)
Find the contiguous subarray within an array (containing at least one number) which has the largest ...
- LeetCode Maximum Product Subarray 解题报告
LeetCode 新题又更新了.求:最大子数组乘积. https://oj.leetcode.com/problems/maximum-product-subarray/ 题目分析:求一个数组,连续子 ...
- leetcode 152. Maximum Product Subarray --------- java
Find the contiguous subarray within an array (containing at least one number) which has the largest ...
- C#解leetcode 152. Maximum Product Subarray
Find the contiguous subarray within an array (containing at least one number) which has the largest ...
- [leetcode]152. Maximum Product Subarray最大乘积子数组
Given an integer array nums, find the contiguous subarray within an array (containing at least one n ...
- Leetcode#152 Maximum Product Subarray
原题地址 简单动态规划,跟最大子串和类似. 一维状态空间可以经过压缩变成常数空间. 代码: int maxProduct(int A[], int n) { ) ; ]; ]; ]; ; i > ...
随机推荐
- Python编译工具Anaconda(含有spyder+jupyter)
Anaconda的下载和安装 官方的下载地址:https://www.anaconda.com/distribution/ 安装程序为一个可执行程序文件,下载完成后双击执行程序即可完成安装.安装过程一 ...
- day31 协程
day31 协程 一.死锁与递归锁 所谓死锁:是指两个或者两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产 ...
- day16 循环导入、模块搜索路径、软件开发、包的使用
day16 循环导入.模块搜索路径.软件开发.包的使用 1.循环导入 循环导入:循环导入问题指的是在一个模块加载/导入的过程中导入另外一个模块,而在另外一个模块中又返回来导入第一个模块中的名字,由于第 ...
- 【swift】长按事件绑定,平移滑动事件+坐标获取
为何把这两个事件归类在一起? 我后来才明白,iOS有一个手势事件(UiGestureRecognizer) 事件里有7个功能,不过我只试过前两个,也就是标题的这两个(长按.平移滑动) UILongPr ...
- Android 清除本地缓存
主要功能:清除内.外缓存,清除数据库,清除Sharepreference,清除files和清除自定义目录 public class DataCleanManager { //清除本应用内部缓存(/da ...
- Android Menu的基本用法
使用xml定义Menu 菜单资源文件必须放在res/menu目录中.菜单资源文件必须使用<menu>标签作为根节点.除了<menu>标签外,还有另外两个标签用于设置菜单项和分组 ...
- D3基础入门四-事件处理
6.5.0版 .on("mouseover", function(e,d) e: {"isTrusted":true} 第二个参考才是数据,但这在不同的环境可能 ...
- Linux:$i 和 ${i}区别
例如你要把有个变量的值和其他字符串连接起来,就需要用到{},以明示{}中的是一个变量. 例如: export var1=ABC export var2=var1=${var1} echo $var2 ...
- spring boot 启动卡半天
测试服务器到期,把环境切了,早上过来 ios 和 安卓 都说 测试环境连不上,ps -ef | grep app.jar 查看了一下进程,发现没有启动,于是 重新打包.部署,一顿骚操作后,监控启动日志 ...
- 基于jar的Spring Boot工程
一.Spring Boot简介 Spring Boot是由Pivotal[ˈpɪvətl]团队(一家做大数据的公司)提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架 ...