Найти все отличия в массиве в 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-й элемент свертки отличен от нуля.