Думайте о каждом диапазоне скоростей как о отрезке на непрерывной числовой линии.Чтобы найти все перекрытия, разделите числовую линию на каждое перекрытие сегмента.
Сначала разделите каждый диапазон на начальную и конечную точки.Допустим, ваши диапазоны:
(5,8) (1,5) (14,17) (3,4) (5,10)
Я собираюсь назначить им буквы для ясности:
A=(5,8) B=(1,5) C=(14,17) D=(3,4) E=(5,10)
Хорошо, теперьДавайте разделим эти диапазоны на отдельные начальные и конечные точки:
A[start]=5, A[end]=8, B[start]=1, B[end]=5, C[start]=14, C[end]=...
и т. д.
Сортируем эти точки по значению, где, если значения равны, начальная точка предшествуетконечная точка, так что вы получите список, подобный следующему:
B[start]=1, D[start]=3, D[end]=4, A[start]=5, E[start]=5, B[end]=5, A[end]=8, ...
и т. д.
Легко, верно?
Теперь просто переберите отсортированный список, сохраняясписок текущих диапазонов.Каждый раз, когда вы приходите к точке [start]
, добавляйте этот диапазон в список.Каждый раз, когда вы приходите к точке [end]
, вынимайте диапазон из списка.
Так что для списка выше вы должны идти:
B[start]=1 add B => (B)
D[start]=3 add D => (B,D)
D[end]=3 remove D => (B)
A[start]=4 add A => (B,A)
E[start]=5 add E => (B,A,E)
B[end]=5 remove B => (A,E)
A[end]=8 remove A => (E)
... and so on
Каждый раз, когда ваш список содержит большечем один элемент, это совпадение.Таким образом, для любого диапазона вы можете точно определить, какие диапазоны перекрываются в любой конкретной точке.
Предполагается, что вы используете алгоритм, такой как быстрая сортировка, для сортировки текущих / конечных точек, это будет O(n log n)
времени выполнения, и обнаружениефактические перекрытия линейны по времени, поэтому весь алгоритм будет работать в O(n log n)
.