Проблема
Предположим, что у меня есть два набора интервалов, названных A и B. Как бы я нашел разницу (относительное дополнение) наиболее эффективным для времени и памяти способом?
Изображение для иллюстрации:
Интервальные конечные точки целые числа (≤ 2 128 -1), и они всегда имеют длину 2 n и выравниваются по m × 2 n (так что вы можете сделать из них двоичное дерево).
Интервалы могут перекрываться во входе, но это не влияет на выход (результат, если сплющенный будет одинаковым).
Проблема заключается в том, что в обеих коллекциях имеется много интервалов (до 100 000 000), поэтому наивные реализации, вероятно, будут медленными.
Ввод считывается из двух файлов и сортируется таким образом, что меньшие промежутки (если они перекрываются) поступают сразу после их родителей в порядке размера. Например:
[0,7]
[0,3]
[4,7]
[4,5]
[8,15]
...
Что я пробовал?
До сих пор я работал над реализацией, которая генерирует двоичное дерево поиска, в то же время делая агрегаты соседних интервалов ([0,3],[4,7] => [0,7]
) из обеих коллекций, затем пересекает второе дерево и "выбивает" интервалы, которые присутствуют в обоих (разделяя большие интервалы в первом дереве, если необходимо).
Пока это работает для небольших коллекций, для хранения самого дерева требуется больше и больше ОЗУ, не говоря уже о времени, которое требуется для завершения вставки и удаления из дерева.
Я понял, что, поскольку интервалы идут предварительно отсортированными, я мог бы использовать какой-то динамический алгоритм и закончить за один проход. Однако я не уверен, что это возможно.
Итак, как я мог бы эффективно решить эту проблему?
Отказ от ответственности: Это не домашнее задание, а модификация/обобщение реальной реальной проблемы, с которой я столкнулся. Я программирую на С++, но могу принять алгоритм на любом [императивном] языке.