LeetCode152
给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续 子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
测试用例的答案是一个 32-位 整数。
请注意,一个只包含一个元素的数组的乘积是这个元素的值。
示例 1:
输入: nums = 2,3,-2,4
**输出:**6
解释: 子数组 2,3 有最大乘积 6。
示例 2:
输入: nums = -2,0,-1
输出: 0
解释: 结果不能为 2, 因为 -2,-1 不是子数组。
Python解法
贪心+分段遍历
python
class Solution:
def maxProduct(self, nums: List[int]) -> int:
max_p = nums[0] # 全局最大乘积,初始为第一个元素
first_neg = 0 # 记录分段里第一个负数的累计乘积,0=本段还没出现负数
pre_p = 1 # 当前段连续乘积,初始乘积基数1
for num in nums:
pre_p = pre_p * num # 累乘当前数字,更新本段连续乘积
max_p = max(max_p, pre_p) # 先拿当前总乘积更新最大值
# 情况1:乘积为负,且本段第一次出现负数 → 保存这个负数乘积
if pre_p < 0 and first_neg == 0:
first_neg = pre_p
# 情况2:本段已经有过负数,现在又算出负乘积
# 删掉【第一个负数及前面所有数】,只保留第一个负数之后的子数组乘积
elif pre_p < 0:
max_p = max(max_p, int(pre_p / first_neg))
# 遇到0:子数组被截断,清空本段所有标记,重新开新段
if num == 0:
pre_p = 1
first_neg = 0
return max_p
以2, -3, -4, -5, 6为例展示过程

核心逻辑

Java解法
贪心+分段遍历
java
public class Solution {
public int maxProduct(int[] nums) {
int max_p = nums[0];
int first_neg = 0;
long pre_p = 1; // long 防止乘积溢出
for (int num : nums) {
pre_p = pre_p * num;
max_p = Math.max(max_p, (int) pre_p);
if (pre_p < 0 && first_neg == 0) {
first_neg = (int) pre_p;
} else if (pre_p < 0) {
int temp = (int)(pre_p / first_neg);
max_p = Math.max(max_p, temp);
}
if (num == 0) {
pre_p = 1;
first_neg = 0;
}
}
return max_p;
}
}
C++解法
贪心+分段遍历
cpp
class Solution {
public:
int maxProduct(vector<int>& nums) {
int max_p = nums[0];
int first_neg = 0;
long long pre_p = 1;
for (int num : nums) {
pre_p *= num;
max_p = max(max_p, (int)pre_p);
if (pre_p < 0 && first_neg == 0) {
first_neg = static_cast<int>(pre_p);
} else if (pre_p < 0) {
int temp = static_cast<int>(pre_p / first_neg);
max_p = max(max_p, temp);
}
if (num == 0) {
pre_p = 1;
first_neg = 0;
}
}
return max_p;
}
};