2025-04-17 12:08:47 +08:00
|
|
|
|
package dynamic_programming;
|
|
|
|
|
/**
|
|
|
|
|
* 题目: 152. 乘积最大子数组 (MaxProduct)
|
|
|
|
|
* 描述:给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续 子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
|
|
|
|
|
* 测试用例的答案是一个 32-位 整数。
|
|
|
|
|
|
|
|
|
|
* 示例 1:
|
|
|
|
|
输入: nums = [2,3,-2,4]
|
|
|
|
|
输出: 6
|
|
|
|
|
解释: 子数组 [2,3] 有最大乘积 6。
|
|
|
|
|
|
|
|
|
|
* 链接:https://leetcode.cn/problems/maximum-product-subarray/
|
|
|
|
|
*/
|
|
|
|
|
//不会
|
2025-07-25 18:23:29 +08:00
|
|
|
|
//二刷不会
|
2025-04-17 12:08:47 +08:00
|
|
|
|
public class MaxProduct {
|
2025-07-25 18:23:29 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 用动态规划维护遍历到当前位置时,以 nums[i] 结尾的「最大乘积」和「最小乘积」:
|
|
|
|
|
* - prevMax:前一步的最大乘积
|
|
|
|
|
* - prevMin:前一步的最小乘积(因为负数相乘会翻转大小)
|
|
|
|
|
* 对于新元素 x = nums[i],候选值只有三种:
|
|
|
|
|
* 1. 单独以 x 为一段子数组
|
|
|
|
|
* 2. 将 x 与 prevMax 相乘(延续最大乘积序列)
|
|
|
|
|
* 3. 将 x 与 prevMin 相乘(延续最小乘积序列,有可能翻转成最大)
|
|
|
|
|
* 因此通过 max(x, x*prevMax, x*prevMin) 得到新的 currMax,
|
|
|
|
|
* 同理用 min(x, x*prevMax, x*prevMin) 得到 currMin。
|
|
|
|
|
* 然后更新全局答案 ans = max(ans, currMax)。
|
|
|
|
|
*/
|
2025-04-17 12:08:47 +08:00
|
|
|
|
public int maxProduct(int[] nums) {
|
|
|
|
|
if (nums == null || nums.length == 0) {
|
|
|
|
|
throw new IllegalArgumentException("数组不能为空");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 初始化:第 0 个位置的最大/最小乘积都等于 nums[0]
|
|
|
|
|
int prevMax = nums[0];
|
|
|
|
|
int prevMin = nums[0];
|
|
|
|
|
int ans = nums[0];
|
|
|
|
|
|
|
|
|
|
// 从 i=1 开始遍历
|
|
|
|
|
for (int i = 1; i < nums.length; i++) {
|
|
|
|
|
int x = nums[i];
|
|
|
|
|
// 三个候选值:x、x*prevMax、x*prevMin
|
|
|
|
|
int candidateMax = Math.max(x, Math.max(x * prevMax, x * prevMin));
|
|
|
|
|
int candidateMin = Math.min(x, Math.min(x * prevMax, x * prevMin));
|
|
|
|
|
|
|
|
|
|
// 更新当前的最大/最小乘积
|
|
|
|
|
prevMax = candidateMax;
|
|
|
|
|
prevMin = candidateMin;
|
|
|
|
|
|
|
|
|
|
// 更新全局答案
|
|
|
|
|
ans = Math.max(ans, prevMax);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ans;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 简单测试
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
MaxProduct sol = new MaxProduct();
|
|
|
|
|
System.out.println(sol.maxProduct(new int[]{2, 3, -2, 4})); // 输出 6
|
|
|
|
|
System.out.println(sol.maxProduct(new int[]{-2, 0, -1})); // 输出 0
|
|
|
|
|
System.out.println(sol.maxProduct(new int[]{-2, 3, -4})); // 输出 24
|
|
|
|
|
System.out.println(sol.maxProduct(new int[]{-1, -3, -10, 0, 60})); // 输出 60
|
|
|
|
|
System.out.println(sol.maxProduct(new int[]{-2, -5, -2, -4, 3})); // 输出 240
|
|
|
|
|
}
|
|
|
|
|
}
|