Сохраняйте информацию о двух самых больших перекрывающихся интервалах max1
и max2
(вначале пустых).
Отсортируйте входной список [x1, y1] .. [xn, yn]
= I1..In
по значению x
, отбрасывая более короткий из двух интервалов, если встречается равенство. Выбрасывая интервалы, обновляйте max1
и max2
.
Для каждого интервала добавьте атрибут max
в линейном времени, показывающий наибольшее значение y
из всех предыдущих интервалов (в отсортированном списке):
rollmax = −∞
for j = 1..n do
Ij.max = rollmax
rollmax = max(rollmax, Ij.y)
В отсортированном, отфильтрованном и расширенном списке ввода выполните следующий запрос. Он использует постоянно расширяющийся подсписок интервалов, меньших, чем искомый в настоящее время интервал Ii
, в качестве входных данных для рекурсивной функции SearchOverlap
.
for i = 2..n do
SearchOverlap(Ii, 1, i − 1)
return {max1, max2}
Функция SearchOverlap
использует подход divide and conquer
для обхода отсортированного списка Il, .. Ir
. Он представляет такой список как полное бинарное дерево с интервалом Ic
в качестве его локального корня. Тест Ic.max < I.max
используется, чтобы всегда принимать решение об обходе бинарного дерева (идти влево/вправо) в направлении интервала с наибольшим перекрытием с I
. Обратите внимание, что I
— это запрошенный интервал, который сравнивается с log(n)
другими интервалами. Также обратите внимание, что при таком обходе может быть пройден максимально возможный интервал перекрытия, отсюда и проверка на наибольшее перекрытие в начале функции SearchOverlap
.
SearchOverlap(I , l, r)
c = ceil(Avg(l, r)) // Central element of queried list
if Overlap(max1, max2) < Overlap(I , Ic) then
max1 = I
max2 = Ic
if l ≥ r then
return
if Ic.max < I.max then
SearchOverlap(I , c + 1, r)
else
SearchOverlap(I , l, c − 1)
return
Наибольшие перекрывающиеся интервалы (если они не пустые) возвращаются в конце. Общая сложность O(n log(n))
.
15.04.2018