LeetCode152. 乘积最大子数组

题目

给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。链接

思路

动态规划,设dp[i]为以nums[i]结尾的连续子数组中乘积最大的值;
dp[i]=max(dp[i-1]*nums[i],nums[i]),由于存在负数,所以需要加一个维度同时存储以num[i]结尾的连续子数组中乘积最大值和最小值,当遇到nums[i]<0时,dp[i]的最大积计算时需要乘以dp[i-1]的最小积,dp[i]的最小积计算时需要乘以dp[i-1]的最大积。

class Solution {
    public int maxProduct(int[] nums) {
        int max=Integer.MIN_VALUE;
        int[][]dp=new int[nums.length][2];
        dp[0][0]=nums[0];
        dp[0][1]=nums[0];
        for(int i=1;i<nums.length;i++){
            if(nums[i]<0){
                dp[i][0]=Math.min(dp[i-1][1]*nums[i],nums[i]);
                dp[i][1]=Math.max(dp[i-1][0]*nums[i],nums[i]);
            }else{
                dp[i][0]=Math.min(dp[i-1][0]*nums[i],nums[i]);
                dp[i][1]=Math.max(dp[i-1][1]*nums[i],nums[i]);
            }
            max=Math.max(max,dp[i][1]);
        }
        return Math.max(max,dp[0][1]);
    }
}

空间优化
由于dp[i]只用到了dp[i-1]的值,可以用滚动变量。当nums[i]为负数时,交换前一个状态最大与最小

class Solution {
    public int maxProduct(int[] nums) {
        int max=Integer.MIN_VALUE,imax=1,imin=1;
        for(int n:nums){
            if(n<0){
                int t=imax;
                imax=imin;
                imin=t;
            }
            imax=Math.max(n,n*imax);
            imin=Math.min(n,n*imin);
            max=Math.max(imax,max);;
        }
        return max;
    }
}

你可能感兴趣的:(LC&Coder)