给定一个double类型的数组arr,其中的元素可正可负可0,返回连续子数组累乘的最大乘积。
数据范围:数组大小满足
,数组中元素满足
进阶:空间复杂度
,时间复杂度
[-2.5,4,0,3,0.5,8,-1]
12.00000
取连续子数组[3,0.5,8]可得累乘的最大乘积为12.00000
[1.0,0.0,0.0]
1.00000
取连续子数组[1.0]可得累乘的最大乘积为1.00000
class Solution {
public:
double maxProduct(vector<double> arr) {
if(arr.size() == 0) {
return 0;
}
double iMax = 1.0, iMin = 1.0;
double ans = arr[0];
for(size_t i = 0; i < arr.size(); i++) {
if(arr[i] < 0) {
std::swap(iMax, iMin);
}
iMax = std::max(arr[i], iMax*arr[i]);
iMin = std::min(arr[i], iMin*arr[i]);
ans = std::max(iMax, ans);
}
return ans;
}
}; public class Solution {
//连续子数组乘积的最大值
public double maxProduct(double[] arr) {
double min=arr[0];
double max=arr[0];
double res=arr[0];
//最大值有可能出现在之前的最小值*当前值,比如最小值为-100,arr[i]<0,同理,最小值也可能出现在之前的最大值,所以每次比较三个值
for(int i=1;i<arr.length;i++){
double last_max=max,last_min=min;
min=Math.min(arr[i],Math.min(arr[i]*last_min,arr[i]*last_max));
max=Math.max(arr[i],Math.max(arr[i]*last_min,arr[i]*last_max));
res=Math.max(max,res);
}
return res;
}
} public class Solution {
public double maxProduct(double[] arr) {
double[] mx = new double[arr.length];
double[] mi = new double[arr.length];
mx[0] = arr[0];
mi[0] = arr[0];
double res = arr[0];
for (int i = 1; i < arr.length; i++) {
mx[i] = Double.max(arr[i], Double.max(mi[i - 1] * arr[i], mx[i - 1] * arr[i]));
mi[i] = Double.min(arr[i], Double.min(mi[i - 1] * arr[i], mx[i - 1] * arr[i]));
if (res < mx[i])
res = mx[i];
}
return res;
}
} class Solution: def maxProduct(self , arr ): maxi, mini, maxproduct = 1, 1, arr[0] for i in range(len(arr)): maxi, mini = max(maxi * arr[i], mini * arr[i], arr[i]), min(maxi * arr[i], mini * arr[i], arr[i]) maxproduct = max(maxi, maxproduct) return maxproduct
class Solution {
public:
double maxProduct(vector<double> arr) {
int len=arr.size();
double curmax=arr[0];
double curmin=arr[0];
double maxnum=curmax;
for(int i=1;i<len;i++) {
double a=arr[i]*curmax;
double b=arr[i]*curmin;
if(a>b) {
curmax=max(a,arr[i]); //以该位置作为尾结点时可能获得的最大值
curmin=min(b,arr[i]); //以该位置作为尾点时可能获得的最小值
} else{
curmax=max(b,arr[i]);
curmin=min(a,arr[i]);
}
maxnum=max(curmax,maxnum);
}
return maxnum;
}
}; 分治算法可解,复杂度O(n*logn)
分治过程:问题划分->求解子问题->合并问题的解。
1.本题分治思路:[L,R]区间上的最大值出现的情况只有3种:
1)在左半区间出现;
2)在右半区间出现;
3)横跨左右半区间出现。
计算以上3种情况的值,返回其中最大值就是最终结果。
2.分治算法的时间复杂度为什么是O(n*logn)?——每次都将区间完美二分,递归过程是一颗二叉树
(1)对于区间[L,R],分割点选取mid=(L+R)>>1,即区间的二分点;
(2)对于长n的区间,最多二分log(n)次:
每次都二分区间,相当于区间长度每次都除以2,最终区间长度为1时停止划分区间:
其中 n/(2^k)=1,2^k=n => k=log(n),
即对于长n的区间最多分割log(n)次,也就是分治递归深度最大为log(n)。
(3)计算第3种情况,需要遍历一遍区间,复杂度O(n):
1)第1层区间[1,n],求解第3种情况的解需遍历一遍区间,复杂度O(n);
2)第2层从第一层划分出两个区间:[1,n/2]和[n/2+1,n],每个子区间求解第3种情况
都要遍历一遍子区间,第二层总复杂度=O(n/2+n/2)=O(n);
3)第3层从第2层划分出4个区间,每个区间长度n/4,复杂度=O(n/4+n/4+n/4+n/4)=O(n);
4)依次类推,每一层都把该层所有的子区间遍历一遍,子区间总长度为n,复杂度O(n)。
(4)每层都要遍历一遍区间,所以总复杂度为:O(递归层数*每层区间长度)=O(log(n)*n)
//代码
public double maxProduct(double[] arr) {
return dfs(arr,0,arr.length-1);
}
//返回区间[l,r]上的最大子数组累乘值
private double dfs(double[] arr,int l,int r){
if(r<l) return 0;
if(l==r) return arr[l];
double ans=0;
int mid=(l+r)>>>1;
double L=dfs(arr,l,mid);//递归计算左半区间最大值
double R=dfs(arr,mid+1,r);//递归计算右半区间最大值
ans=Math.max(L,R);//比较左右子区间的最大值
//计算横跨两个区间的最大值,复杂度O(n).注意处理同负的情况
double maxL=0,minL=0,mulL=1,maxR=0,minR=0,mulR=1;
for(int i=mid;i>=l;i--){//计算分割点左边最大值
mulL*=arr[i];
maxL=Math.max(maxL,mulL);//最大正值
minL=Math.min(minL,mulL);//最大负值
}
for(int i=mid+1;i<=r;i++){//计算分割点右边最大值
mulR*=arr[i];
maxR=Math.max(maxR,mulR);
minR=Math.min(minR,mulR);
}
ans=Math.max(ans,minL*minR);//注意处理同负的情况
ans=Math.max(ans,maxL*maxR);
return ans;
} function maxProduct( arr ) {
// write code here
// 如果数组里面有0或者负数的情况,会影响到数的大小
let min = arr[0];
let max = min;//一开始的数
let res = max;
for(let i=1;i<arr.length;i++){
let last_max = max,last_min = min;
min = Math.min(arr[i],arr[i]*last_min,arr[i]*last_max);//最小的数肯定是从这几个地方来的
max = Math.max(arr[i],arr[i]*last_max,arr[i]*last_min);
res = Math.max(res,max)
}
return res;
} //leetcode中的Maximum Product Subarray问题
//https://leetcode.com/problems/maximum-product-subarray/
public double maxProduct(double[] arr) {
if(arr.length == 0)
return 0;
double maxpre = arr[0];
double minpre = arr[0];
double max = arr[0];
double maxhere, minhere;
for(int i=1; i<arr.length; i++){
maxhere = Math.max(Math.max(maxpre*arr[i], minpre*arr[i]), arr[i]);
minhere = Math.min(Math.min(maxpre*arr[i], minpre*arr[i]), arr[i]);
max = Math.max(max, maxhere);
maxpre = maxhere;
minpre = minhere;
}
return max;
}
class Solution: def maxProduct(self , nums: List[float]) -> float: # write code here dp_max=[1]*len(nums) dp_max[0]=nums[0] dp_min=[1]*len(nums) dp_min[0]=nums[0] for i in range(1,len(nums)): dp_max[i]=max(nums[i],dp_min[i-1]*nums[i],dp_max[i-1]*nums[i]) dp_min[i]=min(nums[i],dp_max[i-1]*nums[i],dp_min[i-1]*nums[i]) return max(max(dp_max),max(dp_min))
class Solution {
public:
double maxProduct(vector<double> arr) {
int n = arr.size();
double ans =0.0;
vector<vector<double>> dp(2, vector<double> (n,0));
dp[0][0]=arr[0],dp[1][0]=arr[0];
ans =arr[0];
for(int i=1;i<n;i++){
dp[0][i] = max(max(dp[0][i-1]*arr[i],dp[1][i-1]*arr[i]),arr[i]);
dp[1][i] = min(min(dp[0][i-1]*arr[i],dp[1][i-1]*arr[i]),arr[i]);
if(ans<dp[0][i]){
ans = dp[0][i];
}
}
return ans;
}
}; public class Solution {
public double maxProduct(double[] arr) {
double max = 0.0 ;
double dp[][] = new double[arr.length][arr.length]; //为了存放最大值
if(arr.length == 1){
return arr[0];
}
int j = 0;
for(int i = 0 ; i < arr.length; i ++){
dp[i][i] = arr[i];
double sum = arr[i];//为了进行累乘
for(j = i + 1 ; j < arr.length; j ++){
if(arr[j] == 0){
dp[i][j] = Math.max(dp[i][j - 1],0);
j = j + 1;//这里是因为,如果不多加一次,那么直接跳出循环,就会到
//22行,此时22行减 了1.
break;
}
sum = sum * arr[j];
dp[i][j] = Math.max(dp[i][j - 1],sum);
}
max = Math.max(max,dp[i][j - 1]);//由于考虑到如果是全部不为0的情况下,那么j一定会多加1,
//所以减掉1
}
return max;
}
} class Solution {
public:
double maxProduct(vector<double> arr) {
if(arr.empty()) return 0;
double res = arr[0];
double imax = 1.0, imin = 1.0;
for(int i=0;i<arr.size();++i){
if(arr[i]==0){
imax = 1.0;
imin = 1.0;
continue;
}
//注意不要先更新imax
double temp = max(arr[i], max(arr[i]*imax, arr[i]*imin));
imin = min(arr[i], min(arr[i]*imax, arr[i]*imin));
imax = temp;
res = max(res, imax);
}
return res;
}
}; public class Solution {
public double maxProduct(double[] arr) {
int n = arr.length;
double mi[] = new double[n + 1];
double ma[] = new double[n + 1];
ma[0] = 1;
mi[0] = 1;
double res = -10101;
for(int i = 1;i <= n;i++){
ma[i] = Math.max(arr[i - 1],arr[i - 1] * ma[i - 1]);
ma[i] = Math.max(ma[i],arr[i - 1] * mi[i - 1]);
mi[i] = Math.min(arr[i - 1],mi[i - 1] * arr[i - 1]);
mi[i] = Math.min(mi[i],arr[i - 1] * ma[i - 1]);
res = Math.max(ma[i],res);
}
return res;
}
} class Solution {
public:
double maxProduct(vector<double> arr) {
if(arr.size() == 1) return arr[0];
double sum = INT_MIN;
vector<vector<double>> dp(arr.size() + 1,(vector<double>(arr.size() + 1,0)));
dp[0][0] = 0;
for(int i = 1; i < arr.size() + 1; i++) dp[i][0] = arr[i - 1];
for(int i = 1; i < arr.size() + 1; i++) dp[0][i] = arr[i - 1];
for(int i = 1; i < arr.size() + 1; i++){
for(int j = i; j < arr.size() + 1; j++){
if(i == j) dp[i][j] = dp[0][j];
else {
dp[i][j] = dp[i][j - 1] * dp[0][j];
}
}
}
for(int i = 0; i < arr.size() + 1; i++){
for(int j = 0; j < arr.size() + 1; j++){
sum = max(sum,dp[i][j]);
}
}
return sum;
}
}; class Solution {
public:
double maxProduct(vector<double> arr) {
int n=arr.size();
double MaxNum=arr[0];
double MinNum=arr[0];
double ans=arr[0];
//最小值也可能变成最大值
//最大值也可能变成最小值
//所以需要维护两个变量
for(int i=1;i<n;i++){
double tmpMax=MaxNum,tmpMin=MinNum;
MaxNum=max(tmpMax*arr[i],max(tmpMin*arr[i],arr[i]));
MinNum=min(tmpMin*arr[i],min(tmpMax*arr[i],arr[i]));
ans=max(ans,MaxNum);
}
return ans;
}
};