2025-07-25 18:23:29 +08:00

68 lines
2.7 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package dynamic_programming;
/**
* 题目: 152. 乘积最大子数组 (MaxProduct)
* 描述:给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续 子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
* 测试用例的答案是一个 32-位 整数。
* 示例 1
输入: nums = [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
* 链接https://leetcode.cn/problems/maximum-product-subarray/
*/
//不会
//二刷不会
public class MaxProduct {
/**
* 用动态规划维护遍历到当前位置时,以 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)。
*/
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
}
}