88.乘积最大子数组

59 阅读1分钟

题目链接

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

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

解法1 暴力解法

思路

最简单的方法就是去连乘,既然是子数组,那么肯定是连续的,两层循环一直找到最大值即可。但是要注意可以是一个子数组。暴力解法可以AC。

代码

function maxProduct(nums: number[]): number {
    let result = nums[0];

    for (let i = 0; i < nums.length; i++) {
        let temp = nums[i];
        for (let j = i + 1; j < nums.length; j++) {
            temp *= nums[j];
            result = Math.max(result, temp, nums[j]);
        }
    }

    return result;
};

时空复杂度

时间复杂度:O(n^2)

空间复杂度:O(1)

解法2 动态规划

思路

如果用动态规划去寻找乘积最大子数组不能简单用“前缀积”来处理,因为如果遇到负数,负数 * 负数 = 正数,所以我们不能只维护最大乘积,还要同时记录最小乘积。

maxSoFar:以 i 结尾的子数组的最大乘积

minSoFar:以 i 结尾的子数组的最小乘积(因为可能为负数)

代码

function maxProduct(nums: number[]): number {
    let result = nums[0];
    let maxSoFar = nums[0];
    let minSoFar = nums[0];

    for (let i = 1; i < nums.length; i++) {
        const cur = nums[i];
        const candidates = [cur, cur * maxSoFar, cur * minSoFar];
        const newMax = Math.max(...candidates);
        const newMin = Math.min(...candidates);

        maxSoFar = newMax;
        minSoFar = newMin;

        result = Math.max(result, maxSoFar);
    }

    return result;
};

时空复杂度

时间复杂度:O(n)

空间复杂度:O(1)