Walking the timeline once

Intervals & Sweep Line

The analogy

You have a pile of bookings and want to know the busiest moment. Rather than comparing every booking with every other, write down every start and every end as an event, sort them by time, then walk the timeline keeping a running count. One pass answers it.

Visualizer

Sweeping the timeline

step 1 / 14
timeline0123456789101112
bk 1โ–ˆโ–ˆโ–ˆโ–ˆ
bk 2โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ
bk 3โ–ˆโ–ˆ
bk 4โ–ˆโ–ˆ
bk 5โ–ˆโ–ˆโ–ˆ
concurrent

Five bookings. What is the maximum number overlapping at once? Comparing every pair with every other is O(nยฒ).5 bookings

def merge_intervals(iv):
    iv.sort()                          # by start
    out = []
    for s, e in iv:
        if out and s <= out[-1][1]:
            out[-1][1] = max(out[-1][1], e)
        else:
            out.append([s, e])
    return out

def max_concurrent(iv):
    events = []
    for s, e in iv:
        events.append((s, +1))
        events.append((e, -1))
    # -1 before +1 at equal time => [start, end) semantics
    events.sort(key=lambda x: (x[0], x[1]))
    cur = best = 0
    for _, delta in events:
        cur += delta
        best = max(best, cur)
    return best

# O(n log n) โ€” the sort dominates
Check yourself

At an identical timestamp, why process end events before start events?