题目描述
给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。测试用例的答案是一个32位整数。
思路
这一题用普通的连续子数组思路求解时有一个问题:子问题的最优解不一定是总体的最优局部解。也就是不满足最优子结构,例如:[-2,3,-4],这个用例中,[-2,3]的最大乘积是3,而不是-6,但是[-2,3,4]的最大乘积需要让-2和3相乘得到-6,然后-6再和-4相乘得到24。解决方式是再维护一个dp数组,也就是一共有两个dp数组,其中一个称为dp_max,另一个称为dp_min。
- dp_max:dp_max[i]表示数组nums中以nums[i]结束的连续子数组的最大乘积。
- dp_min:dp_min[i]表示数组nums中以nums[i]结束的连续子数组的最小乘积。
然后
- 在求解dp_max数组的过程中,把dp_min[i-1] * nums[i]作为一个候选值
- 在求解dp_min数组的过程中,把dp_max[i-1] * nums[i]作为一个候选值
具体步骤
1 确定dp数组的含义
- dp_max:dp_max[i]表示数组nums中以nums[i]结束的连续子数组的最大乘积。
- dp_min:dp_min[i]表示数组nums中以nums[i]结束的连续子数组的最小乘积。
2 确定状态转移方程
dp_max = MAX{nums[i], dp_max[i - 1] * nums[i], dp_min[i - 1] * nums[i]}
dp_min = MIN{nums[i], dp_min[i - 1] * nums[i], dp_max[i - 1] * nums[i]}
3 确定初始状态
初始状态就是dp_max[i] = nums[i]
, dp_min[i] = nums[i]
代码
class Solution {
public int maxProduct(int[] nums) {
int[] dp_max = new int[nums.length];
int[] dp_min = new int[nums.length];
System.arraycopy(nums, 0, dp_max, 0, nums.length);
System.arraycopy(nums, 0, dp_min, 0, nums.length);
for (int i = 1; i < nums.length; i++) {
dp_max[i] = Math.max(Math.max(dp_max[i], dp_max[i - 1] * nums[i]), dp_min[i - 1] * nums[i]);
dp_min[i] = Math.min(Math.min(dp_min[i], dp_min[i - 1] * nums[i]), dp_max[i - 1] * nums[i]);
}
int ans = Integer.MIN_VALUE;
for (int i = 0; i < dp_max.length; i++) {
ans = Math.max(ans, dp_max[i]);
}
return ans;
}
}
标签:152,乘积,nums,int,max,min,数组,LeetCode,dp
From: https://www.cnblogs.com/zawaludo/p/18338994