152. 乘积最大子数组

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

我的思路:本题与53. 最大子序和的区别在于只看前i-1个数的最大值和第i个数是不够的

以2,3,-2为例

F(2)需要看max{{2},{2,3},{3}}

F(3)需要看max{{2},{3},{-2},{2,3},{3,-2},{2,3,-2}}

而根据F(2)我们知道{2},{3},{2,3}谁大只需要通过F(2)就可以知道了,如果没有负数,那么{2,3}再乘一个值肯定是大于{2}乘一个值的,但是由于负数的存在,F(2)中最大的那个如果是正数,而第3个数是负数,则反而会变成最小的;相反如果F(2)中最小的那个如果是负数,而第三个是负数,那么反而会变成最大,所以动态规划时不能只关注最大值,还需要关注最小值,因为都可能在乘上当前这个数后变成最大的

所以动态转移方程为:

 代码如下:

class Solution {
    public int maxProduct(int[] nums) {
        int length = nums.length;
        int[] maxF = new int[length];
        int[] minF = new int[length];
        System.arraycopy(nums, 0, maxF, 0, length);
        System.arraycopy(nums, 0, minF, 0, length);
        for (int i = 1; i < length; ++i) {
            maxF[i] = Math.max(maxF[i - 1] * nums[i], Math.max(nums[i], minF[i - 1] * nums[i]));
            minF[i] = Math.min(minF[i - 1] * nums[i], Math.min(nums[i], maxF[i - 1] * nums[i]));
        }
        int ans = maxF[0];
        for (int i = 1; i < length; ++i) {
            ans = Math.max(ans, maxF[i]);
        }
        return ans;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值