эффективное отсортированное Декартовое произведение 2 отсортированных массива целых чисел
нужно подсказки для разработки эффективного алгоритма, который принимает следующий вход и выплевывает следующий выход.
Input: два отсортированных массива целых чисел A и B, каждый длиной n
вывод: один отсортированный массив, состоящий из декартовых произведений массивов A и B.
For Example:
Input:
A is 1, 3, 5
B is 4, 8, 10
here n is 3.
Output:
4, 8, 10, 12, 20, 24, 30, 40, 50
вот мои попытки решить эту проблему.
1) учитывая, что выход n^2, эффективный алгоритм не может сделать лучше, чем O (n^2) Время сложность.
2) Сначала я попробовал простой, но неэффективный подход. Создайте Декартовое произведение A и B. Это можно сделать в o(n^2) сложности времени. нам нужно хранить, так что мы можем сделать сортировку по нему. Поэтому o (n^2) сложность пространства тоже. Теперь мы сортируем n^2 элементов, которые нельзя сделать лучше, чем O(n^2logn), не делая никаких предположений о входе.
наконец, у меня есть O(n^2logn) время и O (n^2) алгоритм сложности пространства.
должен быть лучший алгоритм потому что я не использовал отсортированный природа входных массивов.
2 ответов
Если есть решение, которое лучше, чем O (n2 log n) он должен сделать больше, чем просто использовать тот факт, что A и B уже отсортированы. См. мой ответ на этот вопрос.
Шрикант удивляется, как это можно сделать в O (n) пространство (не считая пространства для вывода). Это можно сделать, лениво генерируя списки.
предположим, что мы имеем A = 6,7,8 и B = 3,4,5. Во-первых, умножьте каждый элемент в A первым элементом в B и сохраните их в списке:
6×3 = 18, 7×3 = 21, 8×3 = 24
найти наименьший элемент этого списка (6×3), вывести его, заменить его на этот элемент в раз следующий элемент в B:
7×3 = 21, 6×4 = 24, 8×3 = 24
найдите новый наименьший элемент этого списка (7×3), выведите его и замените:
6×4 = 24, 8×3 = 24, 7×4 = 28
и так далее. Нам нужно только O (n) пространство для этого промежуточного списка, и поиск наименьшего элемента на каждом этапе занимает O (log n) время, если мы сохраним список в кучу.
Если вы умножите значение A на все значения B, список результатов все равно будет отсортирован. В вашем примере:
A - 1, 3, 5
B - 4, 8, 10
1*(4,8,10) = 4,8,10
3*(4,8,10) = 12,24,30
теперь вы можете объединить два списка (точно так же, как в сортировке слиянием). Вы просто смотрите на обе головки списка и помещаете меньшую в список результатов. Итак, здесь вы выберете 4, затем 8, затем 10 и т. д. результат = 4,8,10,12,24,30
теперь вы делаете то же самое для списка результатов и следующего оставшегося списка, объединяя 4,8,10,12,24,30 с 5*(4,8,10) = 20,40,50.
поскольку слияние наиболее эффективно, если оба списка имеют одинаковую длину, вы можете изменить эту схему, разделив A на две части, выполнить слияние рекурсивно для обеих частей и объединить оба результата.
обратите внимание, что вы можете сэкономить время, используя подход слияния, поскольку не требуется, чтобы a сортировался, просто B должен быть отсортирован.