给你一个整数数组 nums
,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
我的思路:本题与53. 最大子序和的区别在于只看前i-1个数的最大值和第i个数是不够的
以2,3,-2为例
F(2)需要看max{{2},{2,3},{3}}
F(3)需要看max{{2},{3},{-2},{2,3},{3,-2},{2,3,-2}}
而根据F(2)我们知道{2},{3},{2,3}谁大只需要通过F(2)就可以知道了,如果没有负数,那么{2,3}再乘一个值肯定是大于{2}乘一个值的,但是由于负数的存在,F(2)中最大的那个如果是正数,而第3个数是负数,则反而会变成最小的;相反如果F(2)中最小的那个如果是负数,而第三个是负数,那么反而会变成最大,所以动态规划时不能只关注最大值,还需要关注最小值,因为都可能在乘上当前这个数后变成最大的
所以动态转移方程为:
代码如下:
class Solution {
public int maxProduct(int[] nums) {
int length = nums.length;
int[] maxF = new int[length];
int[] minF = new int[length];
System.arraycopy(nums, 0, maxF, 0, length);
System.arraycopy(nums, 0, minF, 0, length);
for (int i = 1; i < length; ++i) {
maxF[i] = Math.max(maxF[i - 1] * nums[i], Math.max(nums[i], minF[i - 1] * nums[i]));
minF[i] = Math.min(minF[i - 1] * nums[i], Math.min(nums[i], maxF[i - 1] * nums[i]));
}
int ans = maxF[0];
for (int i = 1; i < length; ++i) {
ans = Math.max(ans, maxF[i]);
}
return ans;
}
}