面向小白的力扣152. 乘积最大子数组-动态规划

116 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情

今天,我们继续搞算法。

题目描述

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

测试用例的答案是一个 32-位 整数。

子数组 是数组的连续子序列。

image.png

题目分析

这个题目我们之前做过求和的最大子数组,聪明的你肯定就想了,之前不是做过求和的嘛。直接把这个求和的改成求乘积不就完了嘛?的确是这样,但是如果全正数还好对叭,我们的策略是什么呢?我们的策略就是两个数乘积,当到了i的时候我们把f[i-1]*nums[i],和nums[i]进行对比,取最大,但是如果nums[i]是正数的话,可以,但是如果是负数呢?我们就把这个nums[i]去掉了,去掉之后再来个负数,找不到最大了就,所以我们需要两个策略:是取最大和最小,最小的乘nums[i]和最大的乘nums[i]还有本身取最大,同时我们更新最小,就完成了这道题。

同样,我们要处理一个边界,由于策略有两个,因此数组也是两个,剩下的就和我们求那个最大和是类似的,你完全可以用那里的题改一下。

代码如下:

class Solution {
    public int maxProduct(int[] nums) {
        int m = nums.length;
        int[] fmax = new int[m];
        int[] fmin = new int[m];
        fmax[0]= nums[0];
        fmin[0] = nums[0];
        for(int i =1;i<m;i++){
            fmax[i] =  Math.max(Math.max(fmin[i-1]*nums[i],fmax[i-1]*nums[i]),nums[i]);
            fmin[i] = Math.min( Math.min(fmin[i-1]*nums[i],fmax[i-1]*nums[i]),nums[i]);
        }

        int ans = nums[0];

        for(int i=0;i<m;i++){
            ans = Math.max(fmax[i],ans);
        }

        return ans;

    }
}