152.乘积最大子序列

思路:

  初版思路是将序列按照0拆开成若干子序列,然后在每个子序列里面判断负数的个数,若负数是偶数,直接相乘,若负数是奇数,要么从左往右相乘直到最后一个奇数,要么从右向左相乘知道第一个奇数

  修改版的思路是从左往右遍历+从右往左遍历,使用dp[i]保存相应方向直接相乘到i的数值。碰到0就跳过重新开始计算。

  最终版的思路是使用动态规划,记录以i点结束的最大值跟最小值,然后求max(dp_max * nums[i], dp_min * nums[i]) 与 num[i] 两者之间的最大值。常规dp。

初版:

runtime error

class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int len = nums.size();
        if(len == 0)
            return 0;
        int odd_num = 0;
        int max_num = 1;
        for(int i = 0; i < len; i++)
        {
            if(nums[i] == 0)
            {
                vector<int> vec1(nums.begin(), nums.begin() + i);
                vector<int> vec2(nums.begin() + i+1, nums.end());
                return max(maxProduct(vec1), maxProduct(vec2)) > 0 ? max(maxProduct(vec1), maxProduct(vec2)) : 0;
            }
            if(nums[i] < 0)
                odd_num++;
        }
        if(len == 1)
        {
            return nums[0];
        }
        if(odd_num % 2 == 0)
        {
            for(auto i : nums)
            {
                max_num *= i;
            }
            return max_num;
        }
        else
        {
            bool signal = true;
            int max1 = 1, max2 = 1;
            for(auto i : nums)
            {
                if(!signal)
                    max1 *= i;
                else if(i < 0)
                {
                    signal = false;
                    continue;
                }           }
            signal = true;
            for(int i = nums.size()-1; i >= 0; i--)
            {
                if(!signal)
                    max2 *= nums[i];
                else if(nums[i] < 0)
                {
                    signal = false;
                    continue;
                }
                
            }
            return max(max1, max2);
        }
    }
};

 修改版:

执行用时 :8 ms, 在所有 C++ 提交中击败了77.55%的用户
内存消耗 :9.1 MB, 在所有 C++ 提交中击败了44.38%的用户
class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int len = nums.size();
        if(len == 0)
            return 0;
        vector<int> dp_l(len);
        vector<int> dp_r(len);
        for(int i = 0; i < len; i++)
        {
            dp_l[i] = nums[i];
            dp_r[i] = nums[i];
        }
        int max_l = dp_l[0];
        int max_r = dp_r[0];
        for(int i = 1; i < len; i++)
        {
            if(nums[i] == 0 || dp_l[i-1] == 0)
                continue;
            dp_l[i] = dp_l[i-1] * nums[i];
            max_l = max(max_l, dp_l[i]);
        }
        for(auto i : dp_l)
        {
            max_l = max(i, max_l);
        }
        for(int i = len-2; i >= 0; i--)
        {
            if(nums[i] == 0 || dp_r[i+1] == 0)
                continue;
            dp_r[i] = dp_r[i+1] * nums[i];
            max_r = max(max_r, dp_r[i]);
        }
        for(auto i : dp_r)
        {
            max_r = max(i, max_r);
        }
        return max(max_l, max_r);
    }
};

 最终版:

执行用时 :4 ms, 在所有 C++ 提交中击败了95.67%的用户
内存消耗 :8.9 MB, 在所有 C++ 提交中击败了87.90%的用户
class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int n = nums.size();
        int dp_min = nums[0], dp_max = nums[0];
        int maxVal = nums[0];
        
        for (int i = 1; i < n; ++i) {
            int _dp_min = dp_min * nums[i];
            int _dp_max = dp_max * nums[i];
            
            dp_min = min(nums[i], min(_dp_min, _dp_max));
            dp_max = max(nums[i], max(_dp_min, _dp_max));
            
            maxVal = max(maxVal, dp_max);
        }
        return maxVal;
    }
};

 

posted @ 2019-07-30 18:37  Stoves  阅读(130)  评论(0编辑  收藏  举报