题目原文:
Find the contiguous subarray within an array (containing at least one number) which has the largest product.
For example, given the array [2,3,-2,4],
the contiguous subarray [2,3] has the largest product = 6.
题目大意:
寻找最大乘积的连续子数组。
题目分析:
使用两个dp数组dpmax和dpmin,其中dpmax[i]和dpmin[i]分别表示以i为结尾的子数组的最大、最小乘积。那么初始化dpmax[0]和dpmin[0]均为nums[0],转移方程如下:
dpmax[i]=max(nums[i],dpmax[i−1]∗nums[i],dpmin[i−1]∗nums[i])
dpmin[i]=min(nums[i],dpmax[i−1]∗nums[i],dpmin[i−1]∗nums[i])
这是因为nums[i]可能是正数也可能是负数,如果是负数且前一项的最小积是负数,则会变成最大乘积,而如果最大乘积和最小乘积都是负数或0,且nums[i]是正数,则它本身是最大乘积。所以最大值和最小值可能有三种情况。
源码:(language:java)
public class Solution {
public int maxProduct(int[] nums) {
int length = nums.length;
if(length==0)
return 0;
int[] dpmax = new int[length];
int[] dpmin = new int[length];
dpmax[0] = nums[0];
dpmin[0] = nums[0];
int max = dpmax[0];
for(int i = 1;i<length;i++) {
dpmax[i] = max(nums[i],dpmax[i-1]*nums[i],dpmin[i-1]*nums[i]);
dpmin[i] = min(nums[i],dpmax[i-1]*nums[i],dpmin[i-1]*nums[i]);
if(dpmax[i]>max)
max=dpmax[i];
}
return max;
}
private int max(int a,int b,int c) {
return a>b?(a>c?a:c):(b>c?b:c);
}
private int min(int a,int b,int c) {
return a<b?(a<c?a:c):(b<c?b:c);
}
}
成绩:
5ms,beats 10.47%,众数5ms,36.73%
cmershen 的碎碎念:
(1) 本题如果用一个dp数组,即dp[i][j]维护从i~j的最大乘积,也能实现但会超时。
(2) 对nums很长的情况下,可能会涉及到BigInteger高精度计算,题中没有超过int范围,故test case不够严密。
(3) 这是第一次遇到同时维护多个dp数组的题,也是拓宽了思路。