原文

给你一个整数数组nums,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。测试用例的答案是一个32-位整数。子数组是数组的连续子序列。

这个题还挺有意思的,跟之前的题不太一样。

  • 如果0在子数组中,这个子数组一定乘积为0
  • 所以可以把数组用0分割为若干个数组,再单独从这些数组中寻找子数组
  • 因为是乘法,当数值都是正数时,肯定是子数组元素个数越多乘积越大
  • 负数个数为偶数可以直接当正数
  • 这个题的测试用例数组长度最大2w,肯定不能用O(n^2)的算法
  • 所以一个序列,其中的负数,相当于只有1个或者0个,如果是1个负数,只能是最左侧一个负数或者最右侧一个负数,有一个负数的情况,我们可以把这个序列计算出2个值,没有负数则计算出1个值

我的实现方式比较奇怪,但是能过

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxProduct = function (nums) {
    const arrays = [];
    let array = [];
    for (let i = 0; i < nums.length; i++) {
        if (nums[i] !== 0) {
            array.push(nums[i]);
        } else {
            arrays.push(array);
            array = [];
        }
    }
    arrays.push(array);

    if (arrays.length > 1) {
        arrays.push([0]);
    }
    let p = arrays.map(arr => {
        return product(arr);
    });

    return Math.max(...p);
};

const product = (arr) => {
    if (arr.length === 0) {
        return 0;
    }
    if (arr.length === 1) {
        return arr[0]
    }
    let a = 1;
    let left = 0;
    let right = 0;
    for (let i = 0, len = arr.length - 1; i < arr.length; i++) {
        let nl = arr[i];
        let nr = arr[len - i];
        a *= nl;
        left *= nl;
        right *= nr;
        if (left === 0 && nl < 0) {
            left = 1;
        }
        if (right === 0 && nr < 0) {
            right = 1;
        }
    }

    return Math.max(a, left, right);
};

评论中的一个说法比较简洁,先从左到右乘一遍找到最大值,再从右往左乘一遍找到最大值,比较两个最大值

上一篇 下一篇