码迷,mamicode.com
首页 > 其他好文 > 详细

[LeetCode] Maximum Product Subarray

时间:2015-04-13 16:44:36      阅读:129      评论:0      收藏:0      [点我收藏+]

标签:c++   leetcode   

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.

解题思路:

1、最基本的办法,枚举, 需要的时间复杂度为O(n^2),产生超时。代码如下:

class Solution {
public:
    int maxProduct(int A[], int n) {
        int result=A[0];
        for(int i=1; i<n; i++){
            int product = 1;
            
            for(int j=i; j>=0; j--){
                product *= A[j];
                result = max(result, product);
            }
        }
        return result;
    }
    
    int max(int a, int b){
        return a>b?a:b;
    }
};

2、两边扫描逐步递减法。这是我第一想到的办法,对于一串非0的整数数组元素,先计算他的全部元素的乘积。然后分别从两边扫描,将乘积除以扫描的元素。若结果大于原来的乘积,则继续,否则停止。就题目的例子来说,原来的乘积为-48。从左边开始扫描,-48/2=-24,大于原来的乘积,乘积置为-24,继续扫描。-24/3=-8大于-24,乘积置为-8,继续。-8/-2=4大于-8,乘积置为4,这里剩下一个元素,不再扫描(因为再除的话肯定为1),因此从左边扫描最大的乘积为4。同理,从右边扫描最大的乘积为6。结果取较大值。下面是代码:

class Solution {
public:
    int maxProduct(int A[], int n) {
        vector<int> zeroPos;    //0的位置,0比较特殊
        //为了程序的简单,假设-1处和n处也是0
        zeroPos.push_back(-1);
        for(int i=0; i<n; i++){
            if(A[i]==0){
                zeroPos.push_back(i);
            }
        }
        zeroPos.push_back(n);
        int zeroNum = zeroPos.size();
        int result = A[0];
        for(int i=0; i<zeroNum-1; i++){
            int startPos = zeroPos[i]+1;
            int endPos = zeroPos[i+1]-1;
            if(endPos<startPos){
                continue;
            }
            int tempMax=1;
            for(int j=startPos; j<=endPos; j++){
                tempMax *= A[j];
            }
            //两边扫
            //左边递减
            int leftMax = tempMax;
            for(int j=startPos; j<endPos; j++){
                if(leftMax/A[j] >= leftMax){
                    leftMax /= A[j];
                }else{
                    break;
                }
            }
            result = max(result, leftMax);
            //右边递减
            int rightMax = tempMax;
            for(int j=endPos; j>startPos; j--){
                if(rightMax/A[j]>=rightMax){
                    rightMax /= A[j];
                }else{
                    break;
                }
            }
            result = max(result, rightMax);
        }
        if(zeroNum>2){  //表明原数组内有至少一个0
            result=max(result, 0);
        }
        return result;
    }
    
    int max(int a, int b){
        return a>b?a:b;
    }
};
3、2的办法不容易想到,方法不成体系。可以考虑动态规划。这是我事先未想到的,至今也不是太明白。但大体思路是记录局部的最大值和局部最小值。因为最小值(倘若为负数)乘以一个负数的话,就会转化为最大值。代码如下:

class Solution {
public:
    int maxProduct(int A[], int n) {
        if(n==0){
            return 0;
        }
        if(n==1){
            return A[0];
        }
        int maxLocal;
        int minLocal;
        int result;
        
        result = maxLocal = minLocal = A[0];
        
        for(int i=1; i<n; i++){
            int maxLocalCopy = maxLocal;
            
            maxLocal=max(A[i], maxLocal*A[i]);
            maxLocal=max(maxLocal, minLocal*A[i]);
            
            minLocal=min(A[i], minLocal*A[i]);
            minLocal=min(minLocal, maxLocalCopy*A[i]);
            
            result = max(result, maxLocal);
        }
        return result;
    }
    
    int max(int a, int b){
        return a>b?a:b;
    }
    int min(int a, int b){
        return a>b?b:a;
    }
};
假如数组元素为-4,-3,-2,-1,0,-1,minLocal和maxLocal的取值分别为:

maxLocal: -4 12 8 24 0 0

minLocal:  -4 -4 -24 -8 0 -1

后面如何解释?求科普。

[LeetCode] Maximum Product Subarray

标签:c++   leetcode   

原文地址:http://blog.csdn.net/kangrydotnet/article/details/45025969

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!