Диапазон максимального массива продукта (вариант алгоритма Кадане)
Я пытался получить диапазон максимального продукта подмассива (готовясь к собеседованиям).
Это уже спрашивалось здесь (но никаких действительных ответов предоставлено не было). Получение диапазона максимального массива продукта с использованием алгоритма Каданеса
Трюк / алгоритм хорошо объяснен здесь: http://www.geeksforgeeks.org/maximum-product-subarray/
Я могу легко получить максимальный продукт, но после многих попыток все еще не могу понять, как получить диапазон (левый и правый индексы правильно). Может кто-нибудь, пожалуйста, помогите??
Я вставил свой код, так что вы можете просто скопировать и быстро запустить его..
import java.util.*;
public class ArrayMax {
// maximum product
public static int[] getMaxProduct(int[] list)
{
int max = 1, min = 1, maxProd = 0;
int l = 0, left = 0, right = 0;
for (int i = 0; i < list.length; i++) {
// positive number!
if (list[i] > 0) {
max = max * list[i];
min = Math.min(1, min * list[i]);
}
else if (list[i] == 0) {
max = 1; // reset all
min = 1;
l = i + 1;
}
else {
// hold the current Max
int tempMax = max;
// need to update left here (but how??)
max = Math.max(min * list[i], 1); // [-33, 3]
min = tempMax * list[i]; // update min with prev max
}
// System.out.printf("[%d %d]%n", max, min);
if (max >= maxProd) {
maxProd = max;
right = i;
left = l;
}
}
System.out.println("Max: " + maxProd);
// copy array
return Arrays.copyOfRange(list, left, right + 1);
}
// prints array
public static void printArray(int[] list) {
System.out.print("[");
for (int i = 0; i < list.length; i++) {
String sep = (i < list.length - 1) ? "," : "";
System.out.printf("%d%s", list[i], sep);
}
System.out.print("]");
}
public static void main(String[] args) {
int[][] list = {
{5, 1, -3, -8},
{0, 0, -11, -2, -3, 5},
{2, 1, -2, 9}
};
for (int i = 0; i < list.length; i++) {
int[] res = getMaxProduct(list[i]);
printArray(list[i]);
System.out.print(" => ");
printArray(res);
System.out.println();
}
}
}
Вот примеры выходных данных:
Max: 120
[5,1,-3,-8] => [5,1,-3,-8]
Max: 30
[0,0,-11,-2,-3,5] => [-11,-2,-3,5]
Max: 9
[2,1,-2,9] => [2,1,-2,9]
Как вы видите, я получаю максимальный продукт, но ассортимент ошибочен.
Case#2, Max is 30 (correct answer: [-2,-3,5], showing: [-11,-2,-3,5])
Case#3, Max is 9 (correct answer: [9], giving: [2,1,-2,9])
Пожалуйста помоги.
2 ответа
Проще всего попытаться найти левую позицию / маркер, когда вы вычислили maxProd (в конце). Ваша правая позиция точна, поэтому установите слева направо и делите maxProd по списку [left], пока вы не нажмете 1, уменьшая при этом левую сторону. Вот когда вы достигли левого.
Следующий код перед возвратом должен решить это.
int temp = maxProd;
left = right;
while (temp != 1) {
temp = temp / list[left--];
}
left++;
// copy array
return Arrays.copyOfRange(list, left, right + 1);
Я думаю, что вам нужно отслеживать 2 значения для л. Один будет представлять начальный индекс для подмассива чисел, которые умножаются до максимального значения, а другой будет представлять начальный индекс для подмассива чисел, которые умножаются до минимума.
Однако еще более простой способ - просто подождать, пока вы не найдете максимальный ответ (в maxProd) и его позицию (справа). В этот момент вы можете циклически перебирать массив, умножая элементы списка, пока ваш итог не достигнет maxProd (начиная справа и повторяя в обратном направлении). Последний умноженный элемент должен быть началом подмассива.