这道题,第一眼看上去我就想到dp去优化暴力解法,同时也想到可能滑动窗口也可以解决该问题。但苦苦思索许久,毫无进展最后还是看答案,留下了没有技术的泪水。。。。。。
这道题无论是使用动态规划,还是滑动窗口其实题解相差无几。主要核心就是最小值可能会变为最大值,也就是遇到了负数遇到负数的情况就会导致该情况,也就是需要两个dp保存状态。
动态规划:
public int maxProduct(int[] nums) {
int length = nums.length;
int res = nums[0];
// 以i下标结尾的最小乘积,
int[] minDp = new int[length+1];
int[] maxDp = new int[length+1];
minDp[0] = nums[0];
maxDp[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
if (nums[i] > 0){
maxDp[i] = Math.max(maxDp[i-1]*nums[i],nums[i]);
minDp[i] = Math.min(minDp[i-1]*nums[i],nums[i]);
}else{
maxDp[i] = Math.max(minDp[i-1]*nums[i],nums[i]);
minDp[i] = Math.min(maxDp[i-1]*nums[i],nums[i]);
}
res = Math.max(maxDp[i],res);
}
return res;
}
注意:这个动态规划可以使用滚动变量优化空间复杂度。
滑动窗口:
public int maxProduct2(int[] nums) {
int min = 0;
int max = 0;
int res = -11;
int preMax = 1;
int preMin = 1;
for (int num : nums) {
max = Math.max(num,Math.max(num*preMax,num*preMin));
min = Math.min(num,Math.min(num*preMax,num*preMin));
preMax = max;
preMin = min;
res = Math.max(res,max);
}
return res;
}
注意:就是对于pre初值的初始化,一定要注意使其初始值为1,避免第一个最大值以及最小值出现错误。