2Brute2Best
🔥0

Interval List Intersections

Medium·LeetCode #986Basic Anchor
LeetCode
30-Second Mental ModelIntervals — Intersection of two lists (two pointers)
Complexity:O(M · N)→O(M + N)
Key Insight

Keep i in the first list and j in the second. Compute lo = max(starts) and hi = min(ends). If lo ≤ hi, add [lo, hi]. Then move past the interval that ends first. It can't overlap anything else, because everything later in the other list starts after the other current interval ends.

Core Validity Invariant

Two closed intervals overlap exactly when lo = max(starts) ≤ hi = min(ends), and then the overlap is [lo, hi].

01

Problem

You get two lists of closed intervals, firstList and secondList. A closed interval [a, b] means every number from a to b, including both ends.

Inside each list, the intervals are sorted and don't overlap or touch each other.

Return every place where the two lists overlap, as a list of intervals in order. If two intervals only share one point, that point counts as an interval [x, x].

Input

Two lists of intervals firstList and secondList, where each interval is [start, end].

Output

A list of intervals: the intersection of the two lists, sorted by start. It can be empty.

Example 1
Input: firstList = [[0,2],[5,10],[13,23],[24,25]], secondList = [[1,5],[8,12],[15,24],[25,26]]
Output: [[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]]

[0,2] and [1,5] share [1,2]. [5,10] and [1,5] share only the point 5, so [5,5]. [24,25] and [15,24] share only 24, and [24,25] and [25,26] share only 25.

Example 2
Input: firstList = [[1,3],[5,9]], secondList = []
Output: []

The second list is empty, so nothing overlaps.

Constraints
  • • 0 ≤ firstList.length, secondList.length ≤ 1000
  • • firstList.length + secondList.length ≥ 1
  • • 0 ≤ start < end ≤ 10^9
  • • Within one list: end of one interval < start of the next
02

First, think yourself

Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.

  1. 1.

    Given just two intervals, how do I find the part they share? When do they share nothing?

  2. 2.

    Is touching at one point an overlap here? What does "closed" tell me?

  3. 3.

    Both lists are sorted. Does that remind me of another problem where I walk two sorted lists at once?

  4. 4.

    After comparing one interval from each list, which of the two can never overlap anything else?

  5. 5.

    How many comparisons do I really need if I never go backwards?

03

Brute force approach

05

Optimized approach

06

Why does this algorithm work?

07

Dry run

08

All approaches compared

ApproachIdeaTimeSpace
Brute ForceCompare every interval of the first list with every interval of the secondO(M · N)O(1)
OptimalWalk both lists together; output the overlap, then advance the interval that ends firstO(M + N)O(1)
09

Why does this belong to this pattern?

Clues in the problem statement
  • “two lists, each sorted and disjoint”Walk both lists together with one pointer each, like merging two sorted arrays.
  • “intersection”The overlap of two intervals is [max of starts, min of ends], if that range isn't empty.
  • “closed intervals”Ends are included, so the test is lo ≤ hi and a single point [x, x] counts.
Two sorted interval lists+overlap = [max start, min end]+drop the one that ends first→Intervals — Intersection of two lists (two pointers)

This is the anchor of the sub-pattern. Unlike Merge Intervals, we don't combine intervals from one list. We look at two lists and keep only the time that both cover. The whole idea is one rule: output the overlap, then advance the one that ends first. Meeting Scheduler and Employee Free Time reuse this walk.

10

Don't make this mistake

Advancing both pointers every step
✗ if (lo <= hi) result.push_back({lo, hi}); i++; j++;
✓ if (firstList[i][1] < secondList[j][1]) i++; else j++;

The interval that ends later may still overlap the next interval of the other list. With [[0,10]] and [[1,2],[5,6]], moving both after the first overlap loses [5,6].

Advancing the one with the larger end
✗ if (firstList[i][1] > secondList[j][1]) i++;
✓ if (firstList[i][1] < secondList[j][1]) i++;

The interval with the larger end is the one that can still reach more of the other list. Drop the one that ends first, because it is the one that is finished.

Using lo < hi and losing single points
✗ if (lo < hi) result.push_back({lo, hi});
✓ if (lo <= hi) result.push_back({lo, hi});

The intervals are closed, so [5,10] and [1,5] both include time 5. The answer must include [5,5].

Pattern confusion: merging instead of intersecting

This is not Merge Intervals. Putting both lists together, sorting and merging gives the union (time covered by either list). We want the time covered by both. Also, sorting would waste the fact that both lists are already sorted. Two pointers do it in O(M + N).

11

Want to implement this?

Write it yourself on LeetCode, then come back and compare your code with the solutions above.

Open coding workspace
How did it go?
Beyond The LeetCode Problem

How this concept connects to System Design & C++ Systems

Bridge DSA with production engineering

Top engineering interviews test whether you understand how algorithms like Intervals translate into production architectures and low-level memory mechanics.