Leetcode之Maximum Product Subarray

题目描述

Given an integer array nums, find the contiguous subarray within an array (containing at least one number) which has the largest product.
Example 1:
Input: [2,3,-2,4]
Output: 6
Explanation: [2,3] has the largest product = 6.

解题思路

这个求最大子数组乘积问题是由最大子数组之和问题演变而来,整体思路还是用到了动态规划的方法,但是却比求最大子数组之和要复杂。因为在求和的时候,遇到0,不会改变最大值,遇到负数,也只是会减小最大值而已。而在求最大子数组乘积的问题中,遇到0会使整个乘积为0,而遇到负数,则会使最大乘积变成最小乘积,正因为有负数和0的存在,使问题变得复杂了不少。
方法一:
对于当前的nums[i]值进行了正负情况的讨论:
1. 当遍历到一个正数时,此时的最大值等于之前的最大值乘以这个正数和当前正数中的较大值,此时的最小值等于之前的最小值乘以这个正数和当前正数中的较小值。
2. 当遍历到一个负数时,我们先用一个变量t保存之前的最大值mx,然后此时的最大值等于之前最小值乘以这个负数和当前负数中的较大值,此时的最小值等于之前保存的最大值t乘以这个负数和当前负数中的较小值。
3. 在每遍历完一个数时,都要更新最终的最大值。

class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int res = nums[0], mx = res, mn = res;
        for (int i = 1; i < nums.size(); ++i) {
            if (nums[i] > 0) {
                mx = max(mx * nums[i], nums[i]);
                mn = min(mn * nums[i], nums[i]);
            } else {
                int t = mx;
                mx = max(mn * nums[i], nums[i]);
                mn = min(t * nums[i], nums[i]);
            }
            res = max(res, mx);
        }
        return res;
    }
};

方法二:
这个方法使用了一个trick来将上面解法的分情况讨论合成了一种,巧妙处在于先判断一个当前数字是否是负数,是的话就交换最大值和最小值。那么此时的mx就是之前的mn,所以mx的更新还是跟上面的方法是统一的,而在在更新mn的时候,之前的mx已经保存到mn中了,而且并没有改变,所以可以直接拿来用。

class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int res = nums[0], mx = res, mn = res;
        for (int i = 1; i < nums.size(); ++i) {
            if (nums[i] < 0) swap(mx, mn);
            mx = max(nums[i], mx * nums[i]);
            mn = min(nums[i], mn * nums[i]);
            res = max(res, mx);
        }
        return res;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_21815981/article/details/80151606