Merge and Free Time
What is this?
Two people compare calendars to find a free hour. Nobody does this by checking every pair of meetings against every other — you lay both calendars out in time order and walk down them together. Sorting is what makes that walk possible, and it is the single decision that collapses interval problems from fiddly case analysis into one clean sweep.
Once busy time is merged, free time needs no algorithm at all. It is whatever is left.
whichever ends first — O(m+n), no sort"]
💡 Fun fact:
maxis what makes the merge handle containment without a special case. When[1, 10]is followed by[2, 3], extending withblock.end = max(10, 3)leaves the block untouched — exactly right, because the second interval is entirely swallowed. A naiveblock.end = next.endwould shrink the block to 3 and silently lose seven units of busy time, and the bug only shows up on inputs where one meeting sits inside another.
🔓 The 3 problems in this chapter are free. Sign in with Google or Microsoft to start solving.
The one-line idea: sort by start, then either extend the current block or emit it and begin a new one. Free time is the complement of the merged blocks — and when the inputs are already sorted lists, a two-pointer walk beats sorting them together.
1. The merge sweep
intervals.sort(key=lambda x: x[0])
merged = []
for start, end in intervals:
if merged and start <= merged[-1][1]:
merged[-1][1] = max(merged[-1][1], end) # extend — max handles containment
else:
merged.append([start, end])
Whether the comparison is <= or < is the endpoint convention, and it must be a deliberate choice: with <=, the intervals [1,3] and [3,5] merge into [1,5]; with <, they stay separate. Both are defensible, and problems specify one or the other — state your assumption before you write it.
2. Free time is the complement
Once every person's busy intervals are pooled and merged, the free stretches are simply the gaps:
merged busy: [1,3] [4,6] [7,9]
gaps: [3,4] [6,7]
No extra logic is needed — walk the merged list and emit [previous.end, current.start] whenever there is a positive gap. The common refinement for large inputs is to merge the per-employee schedules with a heap rather than pooling and sorting everything, which is O(n log k) for k employees instead of O(n log n).
3. Two sorted lists need no sort
Meeting Scheduler gives two people's free slots, each already sorted. Sorting them together throws that away. Instead walk both with an index each:
i = j = 0
while i < len(a) and j < len(b):
start = max(a[i][0], b[j][0]) # the overlap begins at the later start
end = min(a[i][1], b[j][1]) # and ends at the earlier end
if end - start >= duration:
return [start, start + duration]
if a[i][1] < b[j][1]: # advance whichever ends first —
i += 1 # it cannot overlap anything later
else:
j += 1
The overlap of two intervals is always [max(starts), min(ends)], and advancing the one that ends first is safe because it can never intersect any later interval on the other side.
4. A 30-second worked example
intervals = [[1,3], [2,6], [8,10], [15,18]]
sorted (already): [1,3] [2,6] [8,10] [15,18]
[1,3] → merged = [[1,3]]
[2,6] → 2 <= 3 → extend: end = max(3, 6) = 6 → [[1,6]]
[8,10] → 8 > 6 → emit and start new → [[1,6], [8,10]]
[15,18] → 15 > 10 → emit and start new → [[1,6], [8,10], [15,18]]
free time between the blocks: [6,8] and [10,15]
The free stretches fell out of the merged list without a single extra comparison.
5. Where you'll actually meet this
- Calendar and scheduling software. Free/busy lookup across several attendees is Employee Free Time exactly.
- Resource booking. Detecting double-bookings for rooms, vehicles or equipment.
- Genomics. Merging overlapping read alignments before computing coverage.
- Log and trace analysis. Collapsing overlapping spans into consolidated activity periods.
- Billing and rostering. Consolidating overlapping shifts or usage windows before invoicing.
6. Problems in this chapter
▶ Merge Intervals
Merge all overlapping intervals. Sort by start, extend with max, emit on a gap.
Pattern: sort-and-sweep merge. Target: O(n log n) time, O(n) space.
▶ Meeting Scheduler
Earliest slot of a given duration free for both people, given two sorted lists of free intervals. Two pointers, advancing whichever interval ends first.
Pattern: two-pointer intersection of sorted lists. Target: O(m + n) time, O(1) space.
▶ Employee Free Time
Time free for every employee. Pool and merge all busy intervals — or merge with a heap for large inputs — then emit the gaps.
Pattern: merge, then take the complement. Target: O(n log n), or O(n log k) with a heap.
7. Common pitfalls 🚫
- Assigning
end = next.endinstead ofmax. Containment silently shrinks the block. - Not deciding the endpoint convention. Whether touching intervals merge changes the answer, and problems differ.
- Sorting already-sorted lists together. Meeting Scheduler is
O(m + n); sorting makes itO((m+n) log(m+n))for nothing. - Advancing the wrong pointer. Advance the interval that ends first — the other may still overlap something later.
- Emitting zero-length gaps. Adjacent merged blocks produce an empty free interval that should be filtered out.
- Forgetting empty input. No intervals means no merged blocks and no free time, not a crash.
- Sorting by end time. It works for "maximum non-overlapping intervals" but not for merging — different problem, different key.
8. Key takeaways
- Sort by start. It is the decision that removes most of the case analysis.
- Extend with
max, which handles containment for free. - Free time is the complement of merged busy time — no second algorithm.
- Already sorted? Use two pointers. Advance whichever interval ends first.
- Overlap is
[max(starts), min(ends)]— worth memorising as a formula. - State the endpoint convention before writing the comparison.
- Why interviewers like it: everyone understands calendars, so the problem statement takes ten seconds and the remaining time is entirely about how carefully you handle the boundaries.
Order: Merge Intervals → Meeting Scheduler → Employee Free Time.
Employee Free Time
Core idea: Each employee hands you a sorted list of busy intervals. You want the windows where nobody is busy — the common free time. The trick is to stop thinking per-employee. Whether a meeting belongs to Alice or to Bob doesn't matter: a moment is free only if it sits outside every busy block. So flatten all busy intervals into one pile, sort them by start, and merge overlaps the same way you'd merge intervals for a single calendar. After merging you're left with a clean, non-overlapping sequence of "somebody is busy" blocks. The gaps between consecutive merged blocks are exactly the moments when everyone is free. Read off those gaps and you're done — O(N log N) for the sort, where N is the total number of intervals.
The problem, rephrased
Picture three colleagues planning a quick stand-up. Each gives you their day as a list of booked time blocks, already sorted, with no overlaps within their own list:
- Alice:
[[1,2], [5,6]] - Bob:
[[1,3]] - Carol:
[[4,10]]
You want every stretch of time when all three are simultaneously free — and only the finite stretches (we ignore "before the day starts" and "after everyone's last meeting," because those run off to infinity). For this group the only finite common gap is [3,4]: Bob frees up at 3, and Carol's [4,10] block starts at 4.
Formally: given schedule, a list where schedule[i] is employee i's sorted, non-overlapping busy intervals, return the list of finite, positive-length common free intervals for all employees, in sorted order.
This is LeetCode 759 — Employee Free Time.
Input schedule |
Common free time (with infinities) | Finite output |
|---|---|---|
[[[1,2],[5,6]],[[1,3]],[[4,10]]] |
[-inf,1], [3,4], [10,inf] |
[[3,4]] |
[[[1,3],[6,7]],[[2,4]],[[2,5],[9,12]]] |
[-inf,1], [5,6], [7,9], [12,inf] |
[[5,6],[7,9]] |
[[[1,4]]] |
[-inf,1], [4,inf] |
[] (single employee, all finite gaps absent) |
We discard any interval containing inf, and we never emit a zero-length interval like [5,5].
Sign in to continue reading
The rest of this lesson is available with a free account. Signing in with Google or Microsoft is free.
Sign in to read the full lesson