1. 程式人生 > 其它 >leetcode-152乘積最大子陣列(兩個轉移方程的正確性證明)

leetcode-152乘積最大子陣列(兩個轉移方程的正確性證明)

1、dp陣列的含義

maxDP[i]中儲存 以nums[i]為結尾元素的子陣列的最大乘積
minDP[i]中儲存 以nums[i]為結尾元素的子陣列的最小乘積

注意到:maxDP[i] >= minDP[i] for all i from 0 to nums.size()-1

2、根據maxDP[i]和minDP[i]的正負,分類討論

情況1:
如果nums[i] == 0
    maxDP[i] 等於 0, 注意:任何數字與0的乘積都是0
    minDP[i] 等於 0, 注意:任何數字與0的乘積都是0 

情況2:
如果nums[i] > 0
    maxDP[i] 等於 max{     nums[i],                         
if maxDP[i-1] <= 0 nums[i]*maxDP[i-1](反證法), if maxDP[i-1] > 0 } 注意:maxDP[i-1]的值,已經覆蓋了所有情況,不必再考慮minDP[i-1] minDP[i] 等於 min{ nums[i], if minDP[i-1] > 0(不能往左乘,越乘越大) nums[i]
*minDP[i-1](反證法), if minDP[i-1] <= 0 } 注意:minDP[i-1]的值,已經覆蓋了所有情況,不必再考慮maxDP[i-1] 情況3: 如果nums[i] < 0 maxDP[i] 等於 max{ nums[i]*minDP[i-1](反證法), if minDP[i-1] < 0 nums[i], if minDP[i-1] => 0 } 注意:minDP[i
-1]的值,已經覆蓋了所有情況,不必再考慮maxDP[i-1] minDP[i] 等於 min{ nums[i]*maxDP[i-1](反證法), if maxDP[i-1] > 0 nums[i], if maxDp[i-1] <= 0 } 注意:maxDP[i-1]的值,已經覆蓋了所有情況,不必再考慮minDP[i-1] 綜上,不論是maxDP[i]還是minDP[i],都是在maxDP[i-1]*nums[i],minDP[i-1]*nums[i],nums[i]這三個數中產生的

maxDP[i]是三個數中最大者,minDP[i]是三個數中最小者


    maxDP[i] = max(maxDP[i-1]*nums[i], max(minDP[i-1]*nums[i], nums[i]))
    minDP[i] = min(minDP[i-1]*nums[i], min(maxDP[i-1]*nums[i], nums[i]))

3、實現

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