这题用动态规划会超时。
其实思路挺简单:
数组中有偶数个负数(或没有负数)就直接返回所有数的乘积。
如果是奇数个负数,要么返回第一个负数后所有数的乘积,要么返回逆序第一个负数左边所有数的乘积。
出发点就以上两点,需要注意数组中有0的情况:把数组按0切成N段,对每段求最大乘积,返回其中最大值。如果每段的乘积都小于0,返回0.
public class Solution {
public int maxProduct(int[] A) {
if (A.length == 0) {
return -1;
}
int p1 = 1;
int max = A[0];
int preIndex = 0;
while (preIndex < A.length && A[preIndex] == 0) {
preIndex++;
}
int i = preIndex;
while (i < A.length) {
if ( A[i] != 0 ) {
p1 *= A[i];
}
if (A[i] == 0 || i == A.length - 1) {
int end = i;
if (A[i] == 0) {
end = i - 1;
}
int sectionP = getMaxInSection(A, preIndex, end, p1);
if (sectionP < 0 && A[i] == 0) { //坑
sectionP = 0;
}
max = Math.max(max, sectionP);
preIndex = i + 1;
while (preIndex < A.length && A[preIndex] == 0) {
preIndex++;
}
i = preIndex;
p1 = 1;
} else {
i++;
}
}
return max;
}
private int getMaxInSection(int[] A, int start, int end, int product) {
if (product > 0) {
return product;
}
if (start == end) {
return product;
}
int leftProduct = 1;
int i = start;
while (i <= end) {
leftProduct *= A[i];
if (A[i] < 0) {
break;
}
i++;
}
if (i == end) { //the only negative in this section is A[end]
return product / A[end];
}
int rightProduct = 1;
int j = end;
while (j >= start) {
rightProduct *= A[j];
if (A[j] < 0) {
break;
}
j--;
}
if (j == start) { //the only negative in this section is A[start]
return product / A[start];
}
return Math.max(product / leftProduct, product / rightProduct);
}
public static void main(String[] args) {
Solution s = new Solution();
int[] a = {0,-3,1,1};
System.out.println( s.maxProduct(a) );
}
}