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.
Meeting Scheduler
Core idea: Sort each person's free slots by start time, then walk two pointers — one per list — in lockstep. At every step the current slots overlap on
[max(starts), min(ends)]; if that window is long enough, you're done. If not, the slot that ends first can never help a later, even-later overlap, so throw it away and advance only that pointer. The slots are random, so sorting is what turns "compare everything to everything" into a single linear sweep.
Problem, rephrased
Two engineers in different time zones both want to pair on a bug, and you're writing the scheduler. Each one hands you their free blocks for the day — a list of [start, end] windows during which they're available — and the pairing session needs duration uninterrupted minutes. Your job: return the earliest duration-long window that falls inside a free block of both people. If there's no such window, return an empty array so the UI can say "no common time."
Formally (LeetCode 1229): given the availability arrays slots1 and slots2 of two people and a meeting duration, return the earliest time slot [start, start + duration] that works for both and is exactly duration long. A slot is an inclusive range [start, end]. It's guaranteed that no two slots of the same person intersect — each person's own blocks are already disjoint. If nothing fits, return [].
![Setup: slots1 = [[10,50],[60,120],[140,210]], slots2 = [[0,15],[60,70]], duration 8; [60,120] and [60,70] overlap on [60,70] (length 10 >= 8), so answer = [60, 68]](https://maangioassets.blob.core.windows.net/diagrams/coding-interview/201/chapters/intervals/merge-and-free-time/meeting-scheduler-diagram-1.svg)
Inputs / outputs
slots1 |
slots2 |
duration |
output | notes |
|---|---|---|---|---|
[[10,50],[60,120],[140,210]] |
[[0,15],[60,70]] |
8 |
[60, 68] |
overlap [60,70] is long enough |
[[10,50],[60,120],[140,210]] |
[[0,15],[60,70]] |
12 |
[] |
longest common window is only 10 |
[[0,100]] |
[[40,60]] |
20 |
[40, 60] |
exact fit — overlap length == duration |
[[0,10]] |
[[20,30]] |
5 |
[] |
the two never overlap at all |
You return a single [start, start + duration] pair — the earliest one — or [].
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