0/23in Data Structures & Algorithms
Data Structures & Algorithms

Interval Patterns

Sort by an endpoint, then sweep. Merging, inserting, and counting overlaps — the shape most scheduling problems take.

~13 minLesson 30 of 60
Your progressNot started

Intervals turn scheduling, calendars, reservations, and ranges into the same shape: each item has a start and an end, and the question is how those spans interact. The hard part is rarely the data structure. It is choosing the right sort order and being precise about overlap.

Most interval solutions start by sorting, then sweeping left to right. Sort by start when you need to merge or insert. Sort by end when you need to choose as many compatible intervals as possible. Use a min-heap of end times when multiple active intervals can overlap at once.

The mental model

For closed intervals like [start, end], two intervals overlap when the next start is at or before the current end:

def overlaps(a, b):
    return a[0] <= b[1] and b[0] <= a[1]

After sorting by start, merging is just keeping one current interval and either extending it or flushing it:

def merge_sorted(intervals):
    merged = []

    for start, end in intervals:
        if not merged or start > merged[-1][1]:
            merged.append([start, end])
        else:
            merged[-1][1] = max(merged[-1][1], end)

    return merged

For room-counting problems, think of a sweep line. Starts add one active meeting; ends remove one. A min-heap stores the earliest ending active meeting, so before placing a new meeting you remove every meeting that already ended.

Meeting rooms usually use half-open time ranges: a meeting ending at 10 does not conflict with one starting at 10. That changes the condition from overlap to reuse: if earliest_end <= start, the room is free.

Merge overlapping intervalsStep 1 / 7
input
1,3
2,6
8,10
9,12
15,16
merged
024681012141618
Sort intervals by start. Overlaps can now only happen with the previous merged interval.
input (sorted)consideringmerged result

Pattern recognition

Variations

Worked problems

Try each yourself before revealing the solution. Watch how the same sorted sweep changes slightly with the question.

LeetCode 56Medium
  • Intervals
  • Sorting
  • Merging

Merge Intervals

Given a list of intervals, combine all overlapping intervals and return a list of non-overlapping ranges that cover the same values.

Approach. Sort by start. The last interval in merged is the only interval that can overlap the next one, because everything before it ends no later. If the next start is beyond the last end, start a new interval. Otherwise extend the last end if needed.

Show solution
def merge(intervals):
    intervals.sort(key=lambda x: x[0])
    merged = []

    for start, end in intervals:
        if not merged or start > merged[-1][1]:
            merged.append([start, end])
        else:
            merged[-1][1] = max(merged[-1][1], end)

    return merged

Complexity. O(n log n) time from sorting and O(n) space for the output. The sweep after sorting is linear.

LeetCode 57Medium
  • Intervals
  • Merging

Insert Interval

You are given sorted, non-overlapping intervals and one new interval. Insert the new interval into the correct position and merge if it overlaps neighbors.

Approach. Because the existing intervals are already sorted, no full sort is needed. Copy every interval that ends before the new interval starts. Then merge all intervals whose start is at or before the new interval’s end. Finally append the merged interval and the untouched suffix.

Show solution
def insert(intervals, new_interval):
    result = []
    i = 0
    n = len(intervals)
    new_start, new_end = new_interval

    while i < n and intervals[i][1] < new_start:
        result.append(intervals[i])
        i += 1

    while i < n and intervals[i][0] <= new_end:
        new_start = min(new_start, intervals[i][0])
        new_end = max(new_end, intervals[i][1])
        i += 1

    result.append([new_start, new_end])
    result.extend(intervals[i:])
    return result

Complexity. O(n) time and O(n) space. Each interval is copied or merged once, and the input’s sorted order is preserved.

LeetCode 253Medium
  • Intervals
  • Heap
  • Sweep line

Meeting Rooms II

Given meeting time ranges, return the minimum number of rooms required so every meeting can be scheduled. A meeting that starts exactly when another ends can use the same room.

Approach. Sort meetings by start time. Keep a min-heap of end times for currently active meetings. Before adding the next meeting, pop every meeting that ended at or before its start. After pushing the new end time, the heap size is the number of rooms active at that moment.

Show solution
import heapq

def min_meeting_rooms(intervals):
    intervals.sort(key=lambda x: x[0])
    active_ends = []
    rooms = 0

    for start, end in intervals:
        while active_ends and active_ends[0] <= start:
            heapq.heappop(active_ends)

        heapq.heappush(active_ends, end)
        rooms = max(rooms, len(active_ends))

    return rooms

Complexity. O(n log n) time and O(n) space. Sorting dominates, and each meeting end is pushed and popped at most once.

The endpoint pitfall

If you are merging coverage, sort by start. If you are maximizing how many intervals survive, sort by end. If you are counting simultaneous activity, sweep with events or a min-heap. Most interval bugs come from using the right idea with the wrong endpoint rule.

Your progressNot started