Найти все отличия в массиве в O (n)
Вопрос: для отсортированного массива A найдите все возможные отличия элементов от A.
Мое решение:
for (int i=0; i<n-1; ++i) {
for (int j=i+1; j<n; ++j) {
System.out.println(Math.abs(ai-aj));
}
}
Конечно, это O (n ^ 2), но я вообще не считаю, что считаю. Я посмотрел онлайн, и я нашел это: http://www.careercup.com/question?id=9111881. В нем говорится, что вы не можете сделать лучше, но на собеседовании мне сказали, что вы можете делать O (n). Что правильно?
Ответы
Ответ 1
Первая мысль заключается в том, что вы не используете тот факт, что массив отсортирован. Пусть это в порядке возрастания (убывание можно обрабатывать аналогично).
Мы также можем использовать тот факт, что телескоп различий (i > j):
a_i - a_j = (a_i - a_(i-1)) + (a_(i-1) - a_(i-2)) + ... + (a_(j+1) - a_j)
Теперь создайте новую последовательность, назовите ее s, которая имеет простую разницу, что означает (a_i - a_(i-1))
. Для этого требуется только один проход (O(n)
), и вы можете также пропустить повторы, что означает пропустить a_i
, если a_i = a_(i+1)
.
Все возможные различия a_i-a_j
с i>j
имеют вид s_i + s_(i+1) + ... + s_(j+1)
. Возможно, если вы считаете, что, найдя их, вы сделали это в O(n)
времени. Однако для их печати может потребоваться не более n(n-1)/2
вызовов, и определенно O(n^2)
.
Ответ 2
Например, для массива с элементами {2 1 2 2,..., 2 n} найдутся n & sdot; (n-1)/2 возможных различий, и ни один из них не равен. Таким образом, существуют различия O (n 2).
Поскольку вам нужно перечислить все из них, вам также потребуется время O (n 2).
Ответ 3
сортировка или несортировка не имеет значения, если вам нужно рассчитать каждую разницу, нет способа сделать это менее чем за n ^ 2,
вопрос был задан неправильно, или вы просто делаете O (n), а затем печатаете 42 других N раз: D
Ответ 4
Если интервьюер увлекается теоретическими играми, возможно, он думал об использовании таблицы входных данных и результатов? Любая проблема с ограничением на размер ввода и известное решение может быть решена путем поиска в таблице. Учитывая, что вы сначала создали и сохранили эту таблицу, которая может быть большой.
Итак, если размер массива ограничен, проблема может быть решена путем поиска в таблице, который (с учетом некоторых допущений) может быть выполнен даже в постоянное время. Разумеется, даже для максимального размера массива из двух (с учетом 32-битных целых чисел) таблица не будет помещаться в обычную память компьютера или на диски. Для больших максимальных размеров массива вы попадаете в размер "не вписывается в известную вселенную". Но, теоретически, это можно сделать.
(Но на самом деле я думаю, что комментарий Йенса Густедта более вероятен.)
Ответ 5
Вы можете получить другой встречный пример, предположив, что содержимое массива представляет собой случайные целые числа перед сортировкой. Тогда вероятность того, что две разности Ai - Aj vs Ak - Al или даже Ai - Aj vs Aj - Ak, одинаковы, слишком мала, чтобы были только O (n) различные разности Ai - Aj.
Учитывая, что вопрос вашему собеседнику заключается в том, чтобы объяснить особые обстоятельства, которые позволяют использовать решение O (n). Одна из возможностей состоит в том, что значениями массива являются все числа в диапазоне 0..n, так как в этом случае максимальная абсолютная разница равна n.
Я могу сделать это в O (n lg n), но не O (n). Представляем содержимое массива массивом размером n + 1 с элементом i, установленным в 1, где в массиве есть значение i. Затем используйте FFT для свертки массива с самим собой - существует разность Ai - Aj = k, где k-й элемент свертки отличен от нуля.