【LeetCode】Maximum Product Subarray 求连续子数组使其乘积最大
Add Date 2014-09-23
Maximum Product Subarray
Find the contiguous subarray within an array (containing at least one number) which has the largest product.
For example, given the array [2,3,-2,4]
,
the contiguous subarray [2,3]
has the largest product = 6
.
简单来说就是在一个 int 数组中找一段连续的子数组,使其乘积最大,数组中包含正数、负数和0。不考虑乘积太大超出范围。
解法一:
动态规划的方法,今天在微信“待字闺中”中看到的,借来分享。遍历一遍,优于解法二,复杂度O(n).
1 int max2(int a, int b) { 2 if(a > b) return a; 3 return b; 4 } 5 6 int max3(int a, int b, int c) { 7 return max2(max2(a, b), c); 8 } 9 10 int min2(int a, int b) { 11 if(a > b) return b; 12 return a; 13 } 14 15 int min3(int a, int b, int c) { 16 return min2(min2(a, b), c); 17 } 18 19 int maxProduct(int A[], int n) { 20 int max = A[0]; 21 int min = A[0]; 22 int a = max; 23 for(int i = 1; i < n; ++i) { 24 int tmpMax = max * A[i]; 25 int tmpMin = min * A[i]; 26 max = max3(tmpMax, tmpMin, A[i]); 27 min = min3(tmpMax, tmpMin, A[i]); 28 a = max2(max, a); 29 } 30 return a; 31 }
解法二:
之前做过找连续子数组使其加和最大,比较简单,见《剑指offer》Q31。
刚开始也试图从那道题中找思路,发现不太科学…后来自己摸索出一个思路,分享一下。
首先,任何一个数字和0相乘得到的都是0;另外,不考虑0的情况下,因为数字都是整数,所以乘积的绝对值是不会变小的;再次,负负得正。
基于这三点考虑,首先基于递归的思想用0分段,也就是说,把数组 A 拆分为 [一段不包含0的数组]、[0]、[剩下的数组],并设 rel1 为不包含0的子数组得到的最大乘积,rel2 为剩下的数组得到的最大乘积,那么,数组 A 的最大乘积就是 max{rel1,0,rel2}。rel2递归的用这个思路得到。
然后,就是求一个不包含0的数组的最大乘积。由于负负得正,可以想到,如果负数的个数为偶数,那么所有的数字相乘就是那个最大乘积;如果负数的个数为奇数,那么一定是某一个负数的左边所有数字乘积或者右边所有数字乘积为最大,所以就可以从前向后遍历数组,并把所有元素相乘,用 numAll1 记录这个乘积,同时每次更新 num1 为从前到后相乘过程中最大的乘积;然后再从后向前遍历数组,用 numAll2 记录乘积,num2 记录最大值,这样整个数组的最大乘积就是 max{num1,num2}。
如果你觉得不理解为什么最大乘积的子数组一定是从第一个数字连续的一个子数组,或者是从最后一个数字连续的子数组,可以这样想:
如果这个乘积最大的子数组是中间的某一段,当然排除掉只有一个元素且为负数的情况,那么这个乘积一定是正数(这个还不懂的话自己想一下吧,简单的),如果
1.这段子数组左边(右边)是全正的,那么和左边(右边)所有的数相乘的结果一定不会比当前的结果小,所以可以从左边(右边)连续;所以这段子数组左边和右边一定都有负数!
2.这段子数组左边(右边)有偶数个负数,同1是不可能的;而且如果有多个负数,一定可以有偶数个可以包含在中间这段子数组中使乘积更大;所以一定左边和右边各有一个负数!
3.如果左边和右边各有一个负数,那么就有两个负数,这样的话把整个数组相乘的结果一定不小于中间这段子数组。
这个算法中遍历整个数组三次,复杂度为O(n).
终于把逻辑说完了,个人觉得很啰嗦,只是想说明白点,不知道大家有没明白,下面附 code,欢迎其它思路。
1 class Solution { 2 public: 3 int maxProductNo0(int A[], int n) { //没有0的数组求最大乘积 4 int num1 = A[0]; 5 int numAll1 = A[0]; 6 for(int i = 1; i < n; ++i) { 7 numAll1 *= A[i]; 8 num1 = numAll1 > num1 ? numAll1 : num1; 9 } 10 11 int num2 = A[n-1]; 12 int numAll2 = A[n-1]; 13 for(int i = n-2; i >= 0; --i) { 14 numAll2 *= A[i]; 15 num2 = numAll2 > num2 ? numAll2 : num2; 16 } 17 return num1 > num2 ? num1 : num2; 18 } 19 20 int maxProduct(int A[], int n) { //求数组最大乘积 21 if(A == NULL || n < 1) 22 return 0; 23 int index0 = 0; 24 int rel1 = A[0]; 25 int rel2 = A[0]; 26 bool have0 = false; 27 for(; index0 < n; ++index0) { 28 if(A[index0] == 0) { 29 have0 = true; 30 break; 31 } 32 } 33 if(index0 > 0) 34 rel1 = maxProductNo0(A, index0); //没有0的数组的最大乘积 35 if(n-index0-1 > 0) 36 rel2 = maxProduct(A+index0+1, n-index0-1); //剩下的数组的最大乘积 37 rel1 = rel1 > rel2 ? rel1 : rel2; 38 if(have0) 39 rel1 = rel1 > 0 ? rel1 : 0; 40 return rel1; 41 } 42 };
转载于:https://www.cnblogs.com/shirley130912/p/4029861.html
【LeetCode】Maximum Product Subarray 求连续子数组使其乘积最大相关推荐
- LeetCode Maximum Product Subarray 解题报告
LeetCode 新题又更新了.求:最大子数组乘积. https://oj.leetcode.com/problems/maximum-product-subarray/ 题目分析:求一个数组,连续子 ...
- php取数组中连续数,PHP实现求连续子数组最大和问题2种解决方法
本文实例讲述了PHP实现求连续子数组最大和问题2种解决方法.分享给大家供大家参考,具体如下: 问题描述 求子数组的最大和 题目描述: 输入一个整形数组,数组里有正数也有负数. 数组中连续的一个或多个整 ...
- Leetcode 剑指 Offer 42. 连续子数组的最大和 (每日一题 20211014)
输入一个整型数组,数组中的一个或连续多个整数组成一个子数组.求所有子数组的和的最大值.要求时间复杂度为O(n).示例1:输入: nums = [-2,1,-3,4,-1,2,1,-5,4] 输出: 6 ...
- 算法--三种方法求连续子数组的最大和
这是一道考的烂的不能再烂的题目,但是依然有很多公司乐于将这样的题目作为笔试或面试题,足见其经典. 题目描述: 输入一个整形数组,数组里有正数也有负数. 数组中连续的一个或多个整数组成一个子数组,每个子 ...
- leetcode剑指 Offer 42. 连续子数组的最大和(动态规划)
输入一个整型数组,数组里有正数也有负数.数组中的一个或连续多个整数组成一个子数组.求所有子数组的和的最大值. 要求时间复杂度为O(n). 示例1: 输入: nums = [-2,1,-3,4,-1,2 ...
- LeetCode -- 剑指 Offer 42. 连续子数组的最大和
剑指 Offer 42. 连续子数组的最大和 线性 DP 题. 针对于数组nums[i] 而言,以它为结尾的子数组分两种情况:(题目限制:必须是连续数组) num[i] 自身作为独立子数组:f[i] ...
- LeetCode Maximum Product Subarray(最大子数组乘积)
Find the contiguous subarray within an array (containing at least one number) which has the large ...
- LeetCode简单题之通过翻转子数组使两个数组相等
题目 给你两个长度相同的整数数组 target 和 arr . 每一步中,你可以选择 arr 的任意 非空子数组 并将它翻转.你可以执行此过程任意次. 如果你能让 arr 变得与 target 相同, ...
- leetcode 643. Maximum Average Subarray I | 643. 子数组最大平均数 I(Java)
题目 https://leetcode-cn.com/problems/maximum-average-subarray-i/ 题解 滑动窗口解法,示意图: 另外,double 计算比 int 要慢, ...
最新文章
- escplise使用教程_eclipse使用教程
- Java 并发编程—有锁互斥机制及AQS理论
- Flink流处理练习
- 从 A/Looper: Could not create epoll instance. errno=24 错误浅谈解决各种 bug 的思路
- Bailian4132 四则运算表达式求值【文本处理】
- 使用FileZilla删除乱码名称文件
- c语言最短线性路径算法,巧用Excel规划求解最短路径
- ipa文件怎么安装到iPhone iPhone怎么安装ipa
- php的toast,toast提示是什么
- 修改webbrower中浏览器版本
- unity android 播放器,Unity3D 安卓视频播放插件 WRP Android Video Player Pro
- 论文分享 | 可控笔触的快速风格化迁移
- Linux上安装oracle19c客户端,Oracle 19c的下载和安装部署(图形安装和静默安装)
- 用VUE实现一个具有登陆、注册等功能的网站【详细步骤】
- 双色球彩票生成之一用户彩票号码随机生成
- spring boot使用jasypt加密原理解析
- Java Web项目开发灵感和知识点总结
- 固定翼无人机1:500地籍
- 基于java的文本/论文查重
- Apache 配置访问日志
热门文章
- Linux下安装vim
- java hashset 实现_HashSet实现原理分析(Java源码剖析)
- BI和报表等于数据分析?终于有人讲清楚了它们的区别
- 电信人的数据应用:销售指引系统
- 参与就有1000块,30W奖池你占一半 | 帆软开发者大赛招募
- 查看php项目tp版本,tp5.1如何查看版本号
- 用python找出所有三位数中的水仙花数_python使用循环打印所有三位数水仙花数的实例...
- zookeeper 虚拟机搭建好后 外部链接不上_Ubuntu Server搭建Hyperledger Fabric 2.1学习环境...
- qcustomplot绘制热力图瀑布图_使用REmap绘制中国地图
- ROS2的学习笔记(legacy)