88.乘积最大子数组

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

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

示例1:

输入: nums = [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。

示例2:

输入: nums = [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。

提示:

  • 1 <= nums.length <= 2 * 104
  • -10 <= nums[i] <= 10
  • nums 的任何子数组的乘积都 保证 是一个 32-位 整数

代码:

class Solution {
    public int maxProduct(int[] nums) {
        //n为nums数组的长度
        int n = nums.length;
        //MaxF[i] 表示以 nums[i] 结尾的子数组的最大乘积
        int[] MaxF = new int[n];
        //MinF[i] 表示以 nums[i] 结尾的子数组的最小乘积(用于处理负数情况)
        int[] MinF = new int[n];
        //初始状态:第一个元素的最大和最小乘积就是它本身
        MaxF[0] = nums[0];
        MinF[0] = nums[0];
        for(int i = 1;i<n;i++){
            //先初始化为当前数字(相当于子数组只包含 nums[i])
            MaxF[i] = nums[i];
            MinF[i] = nums[i];
            //状态转移:
            //1.如果 nums[i] 是正数,MaxF[i] 可能是 MaxF[i-1] * nums[i](正数乘正数更大)
            //2.如果 nums[i] 是负数,MaxF[i] 可能是 MinF[i-1] * nums[i](负数乘负数变正数)
            //3.也可能直接取 nums[i](比如前面乘积是 0,nums[i] 是正数)
            MaxF[i] = Math.max(Math.max(MinF[i-1]*nums[i],MaxF[i]),MaxF[i-1]*nums[i]);
            // 同理,MinF[i] 可能是:
            // 1. MaxF[i-1] * nums[i](正数乘负数变小)
            // 2. MinF[i-1] * nums[i](负数乘负数变大,但这里取最小)
            // 3. 直接取 nums[i](比如前面乘积是 0,nums[i] 是负数)
            MinF[i] = Math.min(Math.min(MaxF[i-1]*nums[i],MinF[i]),MinF[i-1]*nums[i]);
        }
        //初始化为一个极小值
        int res = -0x3f3f3f3f;
        //遍历 MaxF 数组,找出全局最大值
        for(int i = 0;i<n;i++)res = Math.max(res,MaxF[i]);
        //返回最大乘积
        return res;
    }
}
posted @ 2025-05-09 10:19  回忆、少年  阅读(8)  评论(0)    收藏  举报