题目
给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
错误解答
错误在于dp_all这个数组,我用这个数组保存了从头到当前所有数字的连乘,这样做为了保存负数,刚开始没发现错误,
但这个错误很明显:保存了负数但是从头开始算起的,对于那些从中间的负数算起的情况不满足了,比如:2,-5,-2,-4,3。最终结果取-2,-4,3。而我的答案是2,-5,-2。
class Solution {
public int maxProduct(int[] nums) {
int len = nums.length;
int[] dp = new int[len], dp_all = new int[len];
dp[0] = nums[0];
dp_all[0] = nums[0];
for(int i=1; i<len; i++){
dp_all[i] = dp_all[i-1] * nums[i];
dp[i] = nums[i] > nums[i]*dp[i-1] ? nums[i] : nums[i]*dp[i-1];
if(dp_all[i] > dp[i]){
dp[i] = dp_all[i];
}
}
int max = Integer.MIN_VALUE;
for(int i=0; i<len; i++){
if(dp[i] > max){
max = dp[i];
}
}
return max;
}
}
正确解答
正确解答的思路和我的思路是一致的,为了保存下来负数,可以让负负为正的情况保留。
其实,我们用dp数组来保存的是:当前数字为结尾的最大连续子串的结果,保存的是最大值
保存负数的话,用一个dp_min数组来保存最小值,对于奇数个负数的情况来叔,可以找到后两个负数的正结果(比如:-5,-2,-6,dp数组的值为-5,10,12,dp_min的值为-5,-2,-6)
代码实现
class Solution {
public int maxProduct(int[] nums) {
int len = nums.length;
int dp, dp_min, max;
dp = nums[0];
dp_min = nums[0];
max = nums[0];
for(int i=1; i<len; i++){//因为dp[i]只和dp[i-1]有关,所以可以用一个变量来保存,节约了空间
int mx = dp, mn = dp_min;
dp_min = Math.min(mn * nums[i], Math.min(mx * nums[i], nums[i]));
dp = Math.max(mn * nums[i], Math.max(mx * nums[i], nums[i]));
max = Math.max(max, dp);
}
return max;
}
}