Вычислительная разница между двумя большими наборами

14

У меня есть два больших наборов целых чисел A и . Каждый набор содержит около миллиона записей, и каждая запись представляет собой положительное целое число длиной не более 10 цифр. B

Каков наилучший алгоритм для вычисления и ? Другими словами, как я могу эффективно вычислить список записей , которых нет в и наоборот? Какова была бы лучшая структура данных для представления этих двух наборов, чтобы сделать эти операции эффективными?ABBAAB

Лучший подход, который я могу предложить, - это хранить эти два набора в виде отсортированных списков и сравнивать каждый элемент с каждым элементом линейным образом. Можем ли мы сделать лучше?AB

user917279
источник
Если вы хотите сохранить его по-другому, возможно, вы сможете добиться лучших результатов.
Realz Slaw
Кроме того, если вы хотите получить результаты в виде неявной структуры данных; Вы можете просто создать такую ​​структуру, которая запрашивает два набора, чтобы ответить на каждый из его собственных запросов.
Realz Slaw
1
@ user917279 Одна важная вещь: вы обычно можете компромиссировать время предварительной обработки / построения, время запроса и использование памяти друг с другом. Вы редактируете структуру редко, но часто запрашиваете? Наоборот? Память вызывает беспокойство или нет? На такие вопросы можно ответить с практической точки зрения и обосновать выбор «правильной» «теоретической» конструкции.
Рафаэль
1
@ Рафаэль. Вы предлагаете сделать лучше, чем устойчивые наборы (с точки зрения сложности), используя больше памяти и / или тратя больше времени на подготовку. Мне просто любопытно, если вы думаете, что это возможно. Я не вижу таблицы поиска в качестве опции для входных наборов такого размера.
смоссен
1
@ user917279 Если вы рассмотрите пример двух огромных наборов, которые идентичны, то любая структура данных, созданная с использованием хэширования, будет поддерживать проверку на равенство в O (1), так как равные структуры будут объединены при создании и, таким образом, будут использовать одну и ту же область памяти. Слитно-постоянные множества используют преимущества хэширования, когда две структуры почти равны. Сложность - лучшее, что я видел до сих пор для упорядоченных наборов.
смоссен

Ответы:

9

Если вы хотите хранить наборы в специализированной структуре данных, вы можете получить некоторые интересные сложности.

Пусть I=O(min(|A|,|B|,|AΔB|))

Затем вы можете выполнять операции над множествами и A Δ B , каждая в O ( I log | A | + | B |AB,AB,ABAΔBожидаемое время Таким образом, по существу, вы получаете минимальный размер двух наборов или размер симметричной разности, в зависимости от того, что меньше. Это лучше, чем линейное, если симметричная разница мала; то есть. если они имеют большое пересечение. Фактически, для двух требуемых операций разности множеств это практически чувствительно к выходу, поскольку вместе они составляют размер симметричной разности.О(яжурнал|A|+|В|я)

См. Confluently Persistent Sets и Maps by Olle Liljenzin (2013) для получения дополнительной информации.

Реал Слав
источник
Трепа в газете - это упорядоченные деревья поиска. Я бы не считал их несортированными структурами данных.
смоссен
@ Достаточно правдоподобно, я отредактировал это.
Realz Slaw
6

Лучшее, что я знаю, это линейное сканирование, если наборы представлены в виде отсортированных связанных списков. Время работы .О(|A|+|В|)

AВО(|A|×|В|)

AВAВ

difference(A, B):
    if len(B)=0:
        return A # return the leftover list
    if len(A)=0:
        return B # return the leftover list
    if A[0] < B[0]:
        return [A[0]] + difference(A[1:], B)
    elsif A[0] = B[0]:
        return difference(A[1:], B[1:])  # omit the common element
    else:
        return [B[0]] + difference(A, B[1:])

Я представлял это в псевдо-Python. Если вы не читаете Python, он A[0]является главой связанного списка A, A[1:]является остальной частью списка и +представляет собой объединение списков. По соображениям эффективности, если вы работаете в Python, вы, вероятно, не захотите реализовать его точно так же, как описано выше - например, может быть лучше использовать генераторы, чтобы избежать создания многих временных списков - но я хотел показать вам идеи в простейшей форме. Цель этого псевдокода - просто проиллюстрировать алгоритм, а не предложить конкретную реализацию.

AВAВ

DW
источник
фантастика, есть ли у нас другие варианты, если ограничение, что наборы должны быть сохранены как отсортированные списки, снято?
user917279
2

Если A и B имеют одинаковый размер, непересекающиеся и чередующиеся (например, нечетные числа в A и четные числа в B), тогда парное сравнение элементов в линейном времени, вероятно, является оптимальным.

Если A и B содержат блоки элементов, которые находятся точно в одном из A или B или в обоих из них, можно вычислить разность множеств, объединение и пересечение за сублинейное время. Например, если A и B отличаются ровно одним элементом, то разницу можно вычислить в O (log n).

http://arxiv.org/abs/1301.3388

smossen
источник
1
Он говорит, что наборы упорядочены, что может означать, что они хранятся в виде списков, деревьев поиска или чего-то еще. Если данные должны храниться в виде списков, совершенно неинтересно спрашивать «лучший алгоритм для вычисления AB», когда ни один алгоритм не может быть лучше, чем сканирование списков за линейное время (для которого он уже нашел алгоритм).
смоссен
1
черт возьми, вы связали ту же бумагу, что и я (я, как и вы, скорее) ... назовите ваши ссылки в следующий раз: D
Realz Slaw
@smossen фантастика, насколько я знаю (?), я представлял их в виде отсортированных списков, но смиренно приветствовал бы и другие предложения.
user917279
2

NA-Вaб¯a,б

ВЗН
источник
1010
1
Р., упускает суть. один longможет хранить 32 элемента или 1 byte, 8 элементов. Таким образом, 1М записи могут храниться только в ~ 125K RAM! хранилище может быть значительно более эффективным, чем другие представления, в зависимости от того, как реализована проблема ...
vzn
Таким образом, вам понадобится более 12 МБ для наборов, которые интересует OP. Это уничтожает все кэши (в настоящее время) и будет ужасно для редких наборов. В частности, создание пустого набора доминирует над всеми другими операциями (для разреженных наборов). Кстати, Кнут решает эту проблему в TAoCP.
Рафаэль
12MB? да? Плакат сказал, что у него есть только 2 комплекта. на постере не указывалось разреженности / плотности его набора. это указано в моем ответе. Вы предполагаете, что у него есть редкие наборы? Единого правильного ответа не существует, этот подход обозначен как альтернативный вариант, который может быть полезен в зависимости от обстоятельств. это не редкость в этом контексте ...
vzn
10101061010б1,15граммВ