leetcode152 Maximum Product Subarray

求子数组的最大积.

我一开始联想到的是子数组的最大和,动态规划经典题目,但是这道题好像不能用DP来解.

我采用的是一种很直观的解法,求子数组最大积的时候,最特殊的就是0,0乘任何数都等于0.所以,假设有这样的一个数组

1,4,-5,9,-3,-4,0,1,-4,9,7,-3

0把这个数组分成了两个子数组,则最大积就是这两个子数组最大积的最大值(大多数情况下是,暂时不考虑特殊边界条件).所以我们求两个子数组的最大积,那么问题就转换成:不含0的数组求子数组的最大积.

如果不含0的数组包含偶数个负数,则子数组的最大积为所有数字相乘.

如果不含0的数组包含奇数个负数,则子数组的最大积为:max(去除第一个负数及之前的元素所有数字的乘积,去除最后一个负数及之后的元素所有数字乘积).

原数组子数组最大积就是所有不含0的子数组,求子数组最大积,取最大值.

当然,如果所有不含0的子数组,求子数组最大积都为负,则子数组最大积为0,例如:

-2,0,-1这个测试用例.

class Solution {
public:
    int maxProduct(vector<int>& nums) {
        if(nums.empty()) return 0;
        else if(nums.size()==1) return nums[0];
        int zero_point=0;
        int n=(int)nums.size();
        
        int ret=INT_MIN;
        int l=0;
        while(zero_point<n){
            while(zero_point<n && nums[zero_point]!=0) ++zero_point;
            int t=maxProductWithoutZero(nums,l,zero_point);
            //cout<<"t="<<t<<endl;
            ret=max(ret,t);
            while(zero_point<n && nums[zero_point]==0) ++zero_point;
            //cout<<"zero_point="<<zero_point<<endl;
            l=zero_point;
        }
        ret=max(ret,0);
        return ret;
    }
    
    //array doesn't contain zero
    //[l,r)
    //return max product
    int maxProductWithoutZero(vector<int>& nums,int l,int r){
        //cout<<"l="<<l<<" r="<<r<<endl;
        if(l==r-1) return nums[l];
        else if(l==r) return 0;
        int n=0;//amount of negetive number
        int ret=1;
        for(int i=l;i<r;++i){
            if(nums[i]<=0) ++n;
        }
        if(n%2==0){
            for(int i=l;i<r;++i) ret*=nums[i];
        }else{
            int a1=0;
            for(a1=l;a1<r;++a1){
                if(nums[a1]<0) break;
            }
            int num1=1;
            for(int i=a1+1;i<r;++i) num1*=nums[i];
            //cout<<"num1="<<num1<<endl;
            
            int a2=r-1;
            for(;a2>=0;--a2){
                if(nums[a2]<0) break;
            }
            int num2=1;
            for(int i=a2-1;i>=l;--i) num2*=nums[i];
            
            //cout<<"num2="<<num2<<endl;
            ret=max(num1,num2);
        }
        return ret;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值