DSA · Topic 16 of 18 · DP & Advanced Topics

Intervals

Sort by start, then compare each interval with the last one you kept.

6 problems · O(n log n) for the sort time, O(n) for the output space

Step 1 Understand it

Remember it by

Sort by start, then compare each interval with the last one you kept.

Watch it happen

AnimationIntervals: sort by start, then only neighbours can overlap
Read the animation as text
  1. Can one person attend every meeting? Only if no two meetings overlap.
  2. Sort by start time. Then any clash must be between neighbours in the sorted order, so one pass of neighbour checks is enough.
  3. [0, 30] then [5, 10]: the second starts at 5, before the first ends at 30 (5 < 30). A clash: answer False.
  4. Answer: False. Sorting costs O(n log n); the check after it is one pass.

The idea

Interval problems almost always start by sorting. After sorting by start, two intervals overlap exactly when the next one starts before the last one ends. Then merge, count or remove as the problem asks.

Picture it

flowchart LR
  S["sort by start"] --> N["next interval"]
  N --> Q{"start ≤ end of<br/>the last kept?"}
  Q -->|"yes"| M["merge: end = max(both ends)"]
  Q -->|"no"| A["append it"]
  M & A --> N
After sorting, each interval only needs comparing with the last one kept.

Analogy

Putting meetings on a calendar in time order. You only need to compare each meeting with the one just before it to spot a clash.

Where the analogy breaks

A calendar shows everything at a glance. In code, only the sort makes 'compare with the last one' enough; without it you'd have to compare every pair.

More detail

What it is

An Interval is simply a start time and an end time (like a meeting from [1:00 to 2:00]). The 'Intervals' category of problems focuses entirely on giving you a massive list of these start/end times and asking you to find overlaps, merge them, or find free time. It's the exact logic used behind Google Calendar and hotel booking systems!

When to use it

  • When the input is an array of pairs like [[start1, end1], [start2, end2]].
  • When finding overlapping schedules, meeting rooms, or merging data ranges.

How it works

There is a universal 2-step trick to almost every Interval problem.\n1. **Sort the array:** You MUST sort the intervals by their start time. Without sorting, it's impossible to efficiently check overlaps.\n2. **Iterate and Merge:** After sorting, you simply loop through the intervals. If the start time of the *current* interval is strictly less than or equal to the end time of the *previous* interval, they overlap! You merge them by taking the max() of their end times.

Example walkthrough

Input: [[1,3],[2,6],[8,10]]

  1. Sort by start: Already sorted [[1,3], [2,6], [8,10]].
  2. Add [1,3] to our answer list.
  3. Look at [2,6]. The start (2) is less than the previous end (3). OVERLAP! Merge them by taking max(3, 6). Answer list changes to [[1,6]].
  4. Look at [8,10]. The start (8) is greater than previous end (6). No overlap. Just add it. Answer list: [[1,6], [8,10]]

Result: [[1,6], [8,10]]

Related patterns

  • Greedy: Merging intervals is actually a textbook Greedy approach: you optimally merge the current interval before moving on.

Step 2 Recognise it

Words that signal it

  • Input is a list of [start, end] pairs
  • 'Merge overlapping', 'insert an interval'
  • 'Can a person attend all meetings?', 'minimum rooms'
  • 'Remove the fewest intervals so none overlap'

Don't confuse it with

  • Greedy: Non-overlapping Intervals is greedy: sort by END and keep whichever finishes first.
  • Heap: Meeting Rooms II needs how many overlap at once: a min-heap of end times, or sorted starts and ends with two pointers.

Gut check

Pairs of [start, end]? → sort them first, then compare with the last one kept.

How to recognise it in an interview

Input is an array of pairs representing [start, end] ranges.

Step 3 The template

The general shape. Adapt it to each problem rather than learning one solution per problem.

python
def merge(intervals):
    intervals.sort(key=lambda iv: iv[0])     # 1. sort by start
    merged = [intervals[0]]
    for start, end in intervals[1:]:
        last = merged[-1]
        if start <= last[1]:                 # 2. overlaps the last one kept
            last[1] = max(last[1], end)      #    extend it
        else:
            merged.append([start, end])      # 3. no overlap: keep it
    return merged
The same template in Java
text
class Solution {
    public int[][] merge(int[][] intervals) {
        if (intervals.length <= 1) return intervals;
        // Step 1: Sort by starting time
        Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
        
        List<int[]> result = new ArrayList<>();
        int[] currentInterval = intervals[0];
        result.add(currentInterval);
        
        // Step 2: Iterate and check for overlaps
        for (int[] interval : intervals) {
            int currentEnd = currentInterval[1];
            int nextStart = interval[0];
            int nextEnd = interval[1];
            
            if (nextStart <= currentEnd) { // Overlap detected!
                currentInterval[1] = Math.max(currentEnd, nextEnd);
            } else { // No overlap
                currentInterval = interval;
                result.add(currentInterval);
            }
        }
        return result.toArray(new int[result.size()][]);
    }
}
TimeO(n log n) for the sort
SpaceO(n) for the output

Common mistakes

  • Forgetting to sort first.
  • Getting the touching case wrong: does [1, 2] overlap [2, 3]? Read the problem.
  • When merging, setting end = new end instead of max(old end, new end).
  • Trying to merge arrays blindly without updating the reference pointer correctly in Java.

Step 4 Watch it run

Two problems, traced step by step exactly as the code runs.

Easy example: Meeting Rooms

Input: intervals = [[0, 30], [5, 10], [15, 20]]

meetingnext meetingclash?
[0, 30][5, 10]5 < 30? yes → clash

Result: False

Notice: After sorting, a clash can only happen between neighbours, so one pass is enough.

python
def can_attend_meetings(intervals):
    intervals.sort()
    for (s1, e1), (s2, e2) in zip(intervals, intervals[1:]):
        if s2 < e1:
            return False
    return True

Medium example: Merge Intervals

Input: intervals = [[1, 3], [8, 10], [2, 6], [15, 18]]

interval (sorted order)decisionmerged so far
[1, 3]first interval → add it[[1, 3]]
[2, 6]2 ≤ 3 → overlaps; end = max(3, 6) = 6[[1, 6]]
[8, 10]8 > 6 → no overlap, add it[[1, 6], [8, 10]]
[15, 18]15 > 10 → no overlap, add it[[1, 6], [8, 10], [15, 18]]

Result: [[1, 6], [8, 10], [15, 18]]

Notice: Sorting moved [2, 6] next to [1, 3], so the overlap is found by comparing neighbours only.

python
def merge(intervals):
    intervals.sort(key=lambda iv: iv[0])
    merged = [intervals[0][:]]
    for start, end in intervals[1:]:
        if start <= merged[-1][1]:
            merged[-1][1] = max(merged[-1][1], end)
        else:
            merged.append([start, end])
    return merged

Step 5 Practise

Read each question and say the pattern and the trick out loud before you open the answer. Then solve it on LeetCode. Tick a problem once you've solved it on your own: it comes back for review tomorrow, then after 3, 7, 14 and 30 days, then every month, on the DSA page.

Easy

  1. Meeting Rooms Easy

    Decide whether one person can attend all meetings.

    Show answer

    Technique: Sort + check neighbours

    The clue: Any overlap at all.

    The trick: Sort by start; if any meeting starts before the previous one ends, return false.

Medium

  1. Insert Interval Medium

    Insert a new interval into a sorted list of non-overlapping intervals, merging where needed.

    Show answer

    Technique: Intervals: before, overlap, after

    The clue: Already sorted intervals plus one new one.

    The trick: Add the intervals that end before it, merge all that overlap it, then add the rest.

  2. Merge Intervals Medium

    Merge all overlapping intervals.

    Show answer

    Technique: Sort by start + merge

    The clue: 'Merge overlapping'.

    The trick: Sort by start; extend the last kept interval or start a new one.

  3. Non Overlapping Intervals Medium

    Remove the fewest intervals so the rest don't overlap.

    Show answer

    Technique: Greedy: sort by end

    The clue: Keep as many as possible without overlaps.

    The trick: Sort by end and keep each interval that starts after the last kept one ends; count the rest as removed.

  4. Meeting Rooms II Medium

    Find the minimum number of rooms needed for all meetings.

    Show answer

    Technique: Min-heap of end times (or sorted starts and ends)

    The clue: The most meetings happening at the same time.

    The trick: Sort by start; a min-heap holds end times of running meetings; reuse a room when the earliest end ≤ the new start.

Hard

  1. Minimum Interval to Include Each Query Hard

    For each query point, find the size of the smallest interval that contains it.

    Show answer

    Technique: Sort queries + min-heap

    The clue: Many point queries against many intervals.

    The trick: Sort intervals and queries; for each query push intervals that start ≤ q into a heap by size and pop those that end before q.

What to say in the interview

'Because we need to identify overlapping sets, I will first sort the intervals by their start times to guarantee a linear left-to-right sweep.'

Follow-up prep

Can you solve this if you are given a stream of intervals one by one? (Hint: Use a TreeMap).