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; } };
浙公网安备 33010602011771号