Skip to content

Practice problem

Merge Overlapping Bookings

Medium

Solve in Python · graded against 2 sample tests and a hidden test set in your browser · Published

Interactive solution

Solve Merge Overlapping Bookings

Run tries the first sample. Submit checks every sample and additional cases. Your code is saved in this browser.

Ctrl/Cmd+Enter to run

Press Esc then Tab to move keyboard focus out of the code editor.

Ready
Output will appear here after you run your code.

Problem Statement

You're given a list of intervals, each with an integer start and end (start <= end) — think of each one as a booking on a shared resource, occupying every point from its start to its end. Some of these bookings overlap, or even just touch at a single point. Merge every group of overlapping or touching intervals into one interval that spans all of them, and print the resulting intervals, sorted by start, one per line.

Input Format

The input has n + 1 lines:

  • Line 1: a single integer n, the number of intervals.
  • The next n lines: each contains two integers, start and end, with start <= end.

Output Format

Print one line per merged interval, in ascending order of start, each line containing the merged interval's start and end separated by a single space.

Example Walkthrough

Take the first sample: intervals 9-12, 3-7, 14-20, 5-8, given in no particular order. Sorting them by start gives 3-7, 5-8, 9-12, 14-20. Start with 3-7 as the current merged interval. The next interval, 5-8, starts at 5, which is at or before the current interval's end (7), so it overlaps — extend the current interval's end to max(7, 8) = 8, making it 3-8. The next interval, 9-12, starts at 9, which is not at or before the current end (8), so it doesn't overlap — the current interval 3-8 is finished and gets recorded, and 9-12 becomes the new current interval. The last interval, 14-20, starts at 14, past the current end (12), so 9-12 is recorded as finished too, and 14-20 becomes current. With no more intervals left, 14-20 is recorded as the final one. The result: 3-8, 9-12, 14-20 — matching the expected output.

Approach

Comparing every interval to every other interval directly is possible but wasteful, and it's easy to miss chains of overlaps (interval A overlapping B, which overlaps C, even if A and C don't directly overlap). Sorting first turns this into a much simpler problem: once the intervals are ordered by start, any interval that's going to overlap with the interval currently being built up can only be the next one in sorted order, or a later one that still starts early enough — so a single left-to-right sweep, comparing only against the current merged interval, is enough to catch every overlap.

After sorting, keep a "current" interval, initialized to the first one. For each subsequent interval in sorted order, compare its start to the current interval's end. If the new interval's start is at or before that end, the two intervals overlap (or touch) — extend the current interval's end to whichever is larger, its own end or the new interval's end (the new interval's end isn't necessarily larger, since it could be entirely contained within the current interval). If instead the new interval's start comes strictly after the current interval's end, there's a gap: the current interval can't grow anymore, so add it to the result list and make the new interval the current one going forward. After the loop finishes, don't forget to add whatever interval is still "current" to the result — there's no later interval left to trigger that step naturally.

Sorting the intervals costs O(n log n), and the single sweep afterward that merges them touches each interval once, in O(n) — so the total time is dominated by the sort.

Common Mistakes

  • Using strict < instead of <= when checking for overlap. The problem defines touching endpoints (like 7-11 and 11-14) as overlapping. A strict < check would treat them as non-overlapping and leave them as two separate intervals, 7-11 and 11-14, instead of merging them into 7-14.
  • Extending the current interval's end to the new interval's end unconditionally. When an overlapping interval is entirely nested inside the current one — for example, current 1-10 followed by 2-3 — its end (3) is smaller than the current interval's end (10). Overwriting the current end with 3 would incorrectly shrink the merged interval; the end must be updated to the larger of the two.
  • Forgetting to sort the intervals first. The single-pass merge only works because sorted intervals guarantee that anything still able to overlap the current interval appears next in the scan. Without sorting, an interval far later in the input could overlap an interval processed much earlier, and a simple one-pass sweep would miss that merge entirely.

Constraints

  • The input has at least 1 and at most 2,000 intervals.
  • Each interval's start and end are integers with start <= end, and may be negative, positive, or zero.
  • Two intervals are considered overlapping — and must be merged — if one starts at or before the other ends, even if they only touch at a single point.

Target complexity

Time: O(n log n) — dominated by sorting the n intervals by start; the single sweep afterward that merges them is O(n).

Space: O(n) — the sorted list of intervals and the list of merged results each take space proportional to the number of intervals.

Sample tests

Sample 1

Input

4
9 12
3 7
14 20
5 8

Expected output

3 8
9 12
14 20

Sorted by start the bookings are 3-7, 5-8, 9-12, 14-20. 3-7 and 5-8 overlap (5 falls inside 3-7), so they merge into 3-8. 9-12 starts after 8 and 14-20 starts after 12, so neither overlaps anything and they stay as they are.

Sample 2

Input

2
7 11
11 14

Expected output

7 14

7-11 and 11-14 only touch at the single point 11, but touching still counts as overlapping here, so they merge into 7-14.

More problems

All practice problems →