LeetCode每日一题20200518

乘积最大子数组

乘积最大子数组

思路

考虑使用DP,设DP[i]为前i个的最大乘积,很容易的到转移方程
d p [ i ] = m a x ( d p [ i − 1 ] ∗ n u m s [ i ] , a i ) dp[i]=max(dp[i-1]*nums[i],a_i) dp[i]=max(dp[i1]nums[i],ai)

但是显然,这样是不对的,因为会出现负数的情况[5,2,-3,4-3]这样,
dp[4]的状态实际是[52]但是dp[5]需要从[52*-3*4]转移来,所以我们需要一个辅助的DP数组,minF[i]表示前i个的最小值,然后得到的两个转移方程就是
d p [ i ] = m a x ( d p [ i − 1 ] ∗ n u m s [ i ] , m i n ( m i n F [ i − 1 ] ∗ n u m s [ i ] , n u m s [ i ] ) ) dp[i]=max(dp[i-1]*nums[i],min(minF[i-1]*nums[i],nums[i])) dp[i]=max(dp[i1]nums[i],min(minF[i1]nums[i],nums[i]))
m i n F [ i ] = m i n ( m i n F [ i − 1 ] ∗ n u m s [ i ] , m a x ( d p [ i − 1 ] ∗ n u m s [ i ] , n u m s [ i ] ) ) minF[i]=min(minF[i-1]*nums[i],max(dp[i-1]*nums[i],nums[i])) minF[i]=min(minF[i1]nums[i],max(dp[i1]nums[i],nums[i]))
显然可以用滚动数组来优化,最后得到代码

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

你可能感兴趣的:(Leetcode)