最大乘积子数组 给定一个同时包含正整数和负整数的数组,请找到最大积的子数组。 例子:
输入:arr [] = {6,-3,-10,0,2} 输出:子数组为{6,-3,-10}
输入:arr [] = {-1,-3,-10,0,60} 输出:子数组为{60}
输入:arr [] = {-2,-3,0,-2,-40} 输出:子数组为{-2,-40}
注意:查找最大乘积是使用kadane算法完成的,在该示例中,我尝试重用它来查找子数组,但无法破坏查找起始索引的部分,因此查找终止索引很容易。最终索引是res 但无法解决查找子阵列的问题。public int maxProductSubArray(int arr[], int len) {
int res = arr[0];
int max = arr[0];
int min = arr[0];
for (int i = 1; i < len; i++) {
int temp = max;
max = Math.max(Math.max(max * arr[i], min * arr[i]), arr[i]);
min = Math.min(Math.min(temp * arr[i], min * arr[i]), arr[i]);
res = Math.max(res, max);
}
return res;
}
答案 0 :(得分:2)
有几种方法可以解决此问题:
我只会向您展示蛮力解决方案。这不是最快的解决方案,但我认为这是最清晰易懂的解决方案:
public class SubArray {
public static int findMax(int[] num) {
int max = num[0];
int start = 0;
int end = 0;
for(int i = 0; i < num.length; i++) { //Iterating over every possible starting position
for(int j = i; j < num.length; j++) { //Iterating over every possible end position
int multiply = 1;
for(int k = i; k <= j; k++) { //Multiply from start to end
multiply *= num[k];
}
if(max < multiply) { //Did we find a new maximum?
max = multiply;
start = i;
end = j;
}
}
}
System.out.print("The subarray is {"); //Print subarray with highest product
for(int i = start; i <= end; i++) {
System.out.print(num[i]);
if(i < end) {
System.out.print(", ");
}
}
System.out.println("}");
return max;
}
public static void main(String[] args) {
int[] array = {6, -3, -10, 0, 2} ;
int max = findMax(array);
System.out.println("Maximal product is: " + max);
}
}
答案 1 :(得分:0)
通过分而治之可以有效地解决这个问题。
假设您要解决子数组[l, r]
的问题;然后,假设c = (l + r) / 2
是[l, c]
或[c + 1, r]
中的子数组,或是包含c
和c + 1
的某个子数组中的子数组。
然后,我们定义一个函数f(l, r)
来返回子段的答案;然后,要计算此函数,请首先递归调用f(l, c)
和f(c + 1, r)
并选择最大值作为临时答案。然后计算段[c, c]
的乘法,然后计算[c - 1, c]
等(使用multiplication of [c - k, c] = multiplication of [c - k + 1, c] * array[c - k]
),并计算所有此类段的最大和最小乘法。对c
([c + 1, c + 1]
,[c + 1, c + 2]
等右边的段执行相同的操作,然后,答案将是临时答案,即最大值的乘积或最小值的乘法或最小值和最大值的乘积,反之亦然(如果乘积为负,则需要最小乘以最大值)。返回这四个值中的最大值或临时答案作为函数结果。
如果有必要,除了返回乘法函数的值外,还可以返回达到这些值的段。
此解决方案使用Θ(n log n)
时间和Θ(n)
空间。