leetcode-152乘積最大子陣列(兩個轉移方程的正確性證明)
阿新 • • 發佈:2021-10-31
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; } };