持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 20 天,点击查看活动详情
题目链接
题目描述
给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
测试用例的答案是一个 32-位 整数。
子数组 是数组的连续子序列。
测试用例
用例1:
输入: nums = [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
限制
- 1 <= nums.length <= 2 * 10^4
- -10 <= nums[i] <= 10
- nums 的任何前缀或后缀的乘积都 保证 是一个 32-位 整数
题目分析
题目会给定一个元素取值在 [-10, 10] 的数组,需要我们求这个数组里,连续元素的最大乘积
由于数组的组成可能包含由正数、负数、零等任意元素,一个比较常规的思路为:使用一个栈,顺序遍历给定的数组:
- 如果出现的元素为 负数,直接入栈;
- 如果当前的元素为 正数,将其与栈顶的 正数 合并相乘(栈顶无正数则直接压入)
- 如果当前的元素为 0,将栈另存为副本
arr,对arr进行求最大值,清空栈
对 arr 处理的思路如下:
- 如果
arr中存在有偶数个负数,直接相乘即可 - 如果
arr中出现的负数个数为 奇数, 我们将arr划分为: 舍弃第一个负数左边的数组,舍弃最后一个负数右边的数组,分别求他们的乘积,选取其中最大值
代码实现
完整的代码实现如下
var maxProduct = function (nums) {
// 尽量合并相邻的正数,遇到 0 ,计算前面的最大值
let stack = [];
let max = nums[0], indexs = [];
for (let i = 0; i < nums.length; i++) {
let val = nums[i];
if (val == 0) {
caculate(stack);
max = Math.max(0, max)
} else if (val > 0) {
stack.push(val * (stack[stack.length - 1] > 0 ? stack.pop() : 1));
} else {
stack.push(val);
indexs.push(stack.length - 1);
}
}
caculate(stack);
return max;
function maxFunc(arr) {
if (arr.length > 0) max = Math.max(max, arr.reduce((a, b) => a * b))
}
function caculate(arr) {
if (indexs.length % 2 == 0) {
maxFunc(arr)
} else {
let left = indexs[0], right = indexs[indexs.length - 1];
maxFunc(arr.slice(left + 1))
maxFunc(arr.slice(0, right))
}
count = 0;
indexs = [];
stack=[];
}
};