LeetCode 152 乘积最大子数组

1.动态规划数组

class Solution {
    public int maxProduct(int[] nums) {
        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.max(nums[i],dp[i-1][0]*nums[i]);
                dp[i][1]=Math.min(nums[i],dp[i-1][1]*nums[i]);
            }else{
                dp[i][0]=Math.max(nums[i],dp[i-1][1]*nums[i]);
                dp[i][1]=Math.min(nums[i],dp[i-1][0]*nums[i]);
            }
        }
        int max=dp[0][0];
        for(int i=1;i<nums.length;i++){
            max=Math.max(max,dp[i][0]);
        }
        return max;
    }
}

dp[i][j] 代表的意思是  必须以nums[i]结尾的子数组的值,j只有两个值0和1

dp[i][0]代表以nums[i]结尾的子数组的最大值

dp[i][1]代表以nums[i]结尾的子数组的最小值

这个题之所以不能像之前的求连续数组的最大和,就是因为   dp[i][j]和最大值最小值有关系,

正数和负数相乘后,可能直接导致最大值和最小值之间的转换,故期间有状态转移关系

 

接下来,就是推导状态转移方程

这里要分为正数和负数两种情况

 

如果nums[i]>=0       dp[i][0]=Math.max(nums[i],dp[i-1][0]*nums[i]);
                                dp[i][1]=Math.min(nums[i],dp[i-1][1]*nums[i]);

如果nums[i-1]为正数,自然是越乘越大,如果nums[i-1]为负数,自然是选择nums[i]最大

如果nums[i-1]为负数,自然是越乘越这个数越负,越小,如果nums[i-1]为正数,自然是选择nums[i]最小

 

如果nums[i]<0        dp[i][0]=Math.max(nums[i],dp[i-1][1]*nums[i]);
                                 dp[i][1]=Math.min(nums[i],dp[i-1][0]*nums[i]);

如果nums[i-1]为正数,自然是越乘越这个数越负,越小,选择nums[i],如果nums[i-1]为负数,自然是越乘越大,负负得正

如果nums[i-1]为负数,自然是越乘越大,选择nums[i],如果nums[i-1]为正数,自然是选择相乘最小

2.优化

class Solution {
    public int maxProduct(int[] nums) {
        int preMax=nums[0],preMin=nums[0],max=nums[0],temp;
        for(int i=1;i<nums.length;i++){
            if(nums[i]>=0){
                preMax=Math.max(nums[i],preMax*nums[i]);
                preMin=Math.min(nums[i],preMin*nums[i]);
            }else{
                temp=Math.max(nums[i],preMin*nums[i]);
                preMin=Math.min(nums[i],preMax*nums[i]);
                preMax=temp;
            }
            max=Math.max(max,preMax);
        }
        return max;
    }
}

认真观察没有优化之前的代码,可以看出来,主要变量集中在 dp[i-1][0],dp[i-1][1],几乎没有用到动态方程中的其他变量,除了最后遍历的时候需要遍历取最大值,但是其实这个循环也可以放在第一个循环进行,

用preMax,preMin来代替dp[i-1][0],dp[i-1][1],在每次得到preMax后与max比大小,去最大值

除了nums[i]<0处,preMax需要一个temp临时变量先存储一下值

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值