leetcode 152 乘积最大子数组

65 阅读1分钟

这道题,第一眼看上去我就想到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,避免第一个最大值以及最小值出现错误。