题意思路:

给定一个double类型的数组arr,其中的元素可正可负可0,返回子数组累乘的最大乘积。

方法一:暴力枚举

每次选取当前元素的所有子数组判断得到的最大值

复杂度分析

时间复杂度:O(),表示数组的长度。

空间复杂度:O()。除了几个临时变量外,没有额外的空间。

class Solution {
public:
    double maxProduct(vector<double> arr) {
       double ans=arr[0];
        for(int i=0;i<arr.size();i++){//循环每个元素
            double res=1;
            for(int j=i;j<arr.size();j++){//枚举以当前i元素为起点的子矩阵
                res*=arr[j];
                ans=max(ans,res);
            }
        }
        return ans;
    }
};

方法二:动态规划

求数组的所有子矩阵,因为乘积的结果由连续的数组得到,而且数组中会有0和负数,

两个负数相乘的结果也许大于最大值,所有我们也要记录当前子矩阵的最小值

通过从集合角度可以分析出状态转移方程:

可以使用滚动数组优化,每次都使用固定的几个存储空间,来达到压缩,节省存储空间的作用。起到优化空间,主要应用在递推或动态规划中。

因为DP题目是一个自底向上的扩展过程,我们常常需要用到的是连续的解,前面的解往往可以舍去。所以用滚动数组优化是很有效的。

图文详解:
图片说明
复杂度分析

时间复杂度:O(),表示数组的长度。

空间复杂度:O()。除了几个临时变量外,没有额外的空间。

class Solution {
public:
    double maxProduct(vector<double> arr) {
       double mi=arr[0],mx=arr[0],ans=arr[0];
        for(int i=1;i<arr.size();i++){//滚动数组 不需要开数组记录
            double last_mx=mx;//会覆盖当前更新完fmax,所以需要特殊记录
            mx=max(max(arr[i],arr[i]*mx),arr[i]*mi);//状态转移方程
            mi=min(min(arr[i],arr[i]*last_mx),arr[i]*mi);
            ans=max(ans,mx);
        }
        return ans;
    }
};