AlgoMaster Logo

Introduction to Intervals

High Priority23 min readUpdated May 30, 2026
Listen to this chapter
Unlock Audio

A calendar application needs to schedule a new meeting from 2pm to 4pm against existing meetings from 1pm to 3pm and 3:30pm to 5pm. Does the new meeting conflict? How do you check this efficiently for hundreds of meetings?

This is an interval problem. Intervals appear everywhere in software: calendar systems, booking platforms, resource allocation, genomic data analysis, network packet scheduling, and database query optimization. Detecting overlaps, merging ranges, and finding gaps efficiently is a core skill.

Determining overlap correctly, handling edge cases, and doing it efficiently for thousands of intervals requires careful thinking. A few patterns cover most interval problems.

This chapter uses closed intervals [start, end] throughout. The overlap condition is a.start <= b.end && b.start <= a.end. For half-open [start, end) problems (common in scheduling APIs like Meeting Rooms II), replace <= with < so that meeting [1,5) does not conflict with [5,8).

What Is an Interval?

An interval represents a continuous range with a start and end point. In coding problems, intervals are typically represented as arrays or objects with two values.

Intervals can be:

  • Closed: Both endpoints are included, written as [a, b]
  • Open: Both endpoints are excluded, written as (a, b)
  • Half-open: One endpoint included, written as [a, b) or (a, b]

Most LeetCode problems use closed intervals [start, end], meaning both the start and end values are part of the interval.

Core Concepts

Detecting Overlap

The most common interval question is whether two intervals overlap.

Given interval A = [a, b] and interval B = [c, d], they overlap if and only if:

This condition checks that A starts before B ends AND B starts before A ends. It is often easier to think about the negation: two intervals do NOT overlap if:

This means either A ends before B starts, or B ends before A starts.

The "touch at endpoint" case (where one interval ends exactly where another starts) frequently causes off-by-one bugs. Whether [1,5] and [5,8] are considered overlapping depends on whether the problem uses closed or half-open intervals. Read the problem statement carefully.

Sorting Strategies

Most interval algorithms begin with sorting. The two common approaches are:

Sort by start time: Used for merging intervals. After sorting, overlapping intervals become adjacent, making them easy to merge in a single pass.

Sort by end time: Used for interval selection problems (like activity selection). By always picking the interval that ends earliest, you leave maximum room for subsequent intervals. The exchange-argument proof: any optimal schedule can be transformed into the greedy one by swapping each interval with the earliest-ending compatible alternative without reducing the count.

Sort ByUse CaseWhy It Works
Start timeMerge overlapping intervalsOverlapping intervals become consecutive
End timeSelect maximum non-overlappingEarliest end leaves most room for others
Start time (then by end)Insert into sorted listMaintain sorted order for binary search

Tie-Breaking in Sort Comparators

When intervals share start or end times, secondary sort order can change correctness.

  • Sweep line: for half-open intervals [s, e), an end event at time t should come before a start event at time t so that back-to-back meetings do not double-count. For closed intervals [s, e], the order reverses.
  • Greedy by end time (LC 435 Non-overlapping Intervals, LC 452 Minimum Arrows): when two intervals share the same end value, either order yields a correct count, but stable sorts give reproducible output across runs.
  • Sort by start time (Meeting Rooms II): ties on start are usually irrelevant because both intervals are equally claimable, though some problems require a secondary sort by end time to make the iteration deterministic.

Read the problem statement carefully for inclusive vs. exclusive endpoint semantics before writing the comparator.

Merging Two Intervals

When two intervals overlap, merging them creates a single interval:

The merged interval starts at whichever interval started earlier and ends at whichever ended later.

Canonical Problem: Merge Intervals (LC 56)

Problem: given a list of intervals, merge all overlapping intervals and return the result.

Approach

  1. Sort the intervals by start time. Once sorted, any pair of overlapping intervals will sit next to each other in the array.
  2. Iterate through the sorted list. For each interval, either merge it into the last interval in the result list (if they overlap) or append it as a new entry.

The merge step expands the last result interval's end to max(last.end, current.end). The end of the last interval can only grow, never shrink, so a single pass is enough.

Walkthrough

Trace on [[1,3],[2,6],[8,10],[15,18]]:

  • After sort: [[1,3],[2,6],[8,10],[15,18]] (already sorted).
  • Initialize result = [[1,3]] with the first interval.
  • [2,6]: 2 <= 3 (overlap), merge by setting end to max(3, 6) = 6. result = [[1,6]].
  • [8,10]: 8 > 6 (no overlap), append. result = [[1,6],[8,10]].
  • [15,18]: 15 > 10 (no overlap), append. result = [[1,6],[8,10],[15,18]].

Final result: [[1,6],[8,10],[15,18]].

Implementation

Time Complexity: O(n log n) for the sort, O(n) for the merge pass. Total: O(n log n).

Space Complexity: O(n) for the output list. Auxiliary space is O(log n) for the sort on most implementations.

Canonical Problem: Insert Interval (LC 57)

Problem: given a sorted, non-overlapping interval list and a new interval, insert the new interval and merge any resulting overlaps.

Approach

Walk through the input list in three phases:

  1. Before phase: append every interval that ends before the new interval starts. These intervals cannot overlap with the new one.
  2. Merge phase: for every interval that overlaps with the new interval, expand the new interval's bounds: newInterval[0] = min(newInterval[0], current[0]) and newInterval[1] = max(newInterval[1], current[1]).
  3. After phase: append the merged new interval, then append every remaining interval (which all start after the new interval ends).

Because the input is already sorted, a single pass is enough. No global sort is needed, so the work is linear in the input size.

Walkthrough

Trace on intervals = [[1,3],[6,9]], newInterval = [2,5]:

  • Phase 1: [1,3] ends at 3, and 3 is not less than newInterval[0] = 2. Stop the before phase without appending.
  • Phase 2: [1,3] starts at 1, which is <= newInterval[1] = 5, so they overlap. Update newInterval = [min(2,1), max(5,3)] = [1,5]. Advance to [6,9]. 6 > 5, so the merge phase ends.
  • Phase 3: append newInterval = [1,5], then append [6,9].

Final result: [[1,5],[6,9]].

Implementation

Time Complexity: O(n) since each input interval is visited once.

Space Complexity: O(n) for the output list.

Canonical Problem: Meeting Rooms (LC 252, LC 253)

Two related problems use the same input shape but answer different questions.

Meeting Rooms I (LC 252)

Problem: given an array of meeting time intervals, determine whether a single person can attend all meetings without conflicts.

Approach: sort by start time. For each consecutive pair, return false if the previous meeting's end is greater than the current meeting's start. Half-open semantics treat [1,5] and [5,8] as non-conflicting (the room frees at end time).

This is a building block. The harder cousin asks for the minimum number of rooms.

Meeting Rooms II (LC 253)

Problem: given an array of meeting time intervals, return the minimum number of conference rooms required to host all meetings.

Approach (min-heap by end time): sort intervals by start time. Maintain a min-heap of meeting end times. For each new meeting, check whether the earliest-ending meeting on the heap has already ended (its end time is at or before the new meeting's start). If yes, pop it (that room is now free). Push the new meeting's end time. The heap size at any moment equals the number of rooms currently in use, and the maximum heap size during the iteration is the answer. Because the heap can only shrink when a room is freed and only grows when a new meeting starts, its final size is also the maximum size reached.

Walkthrough

Trace on [[0,30],[5,10],[15,20]]:

  • Sort by start: [[0,30],[5,10],[15,20]] (already sorted).
  • [0,30]: heap empty, push 30. Heap = [30].
  • [5,10]: heap top is 30, and 30 > 5, so no room is free. Push 10. Heap = [10, 30].
  • [15,20]: heap top is 10, and 10 <= 15, so that room is free. Pop 10, push 20. Heap = [20, 30].
  • Final heap size: 2.

Answer: 2 rooms.

Implementation

Time Complexity: O(n log n) for the sort plus O(n log n) for heap operations.

Space Complexity: O(n) for the heap in the worst case (all meetings concurrent).

Approach 2 (sweep line / chronological events): treat each meeting as two events, +1 at its start and -1 at its end. Sort the events by position, then sweep through them while tracking a running counter. The maximum value of the counter is the answer. This runs in O(n log n) with a different constant factor and shares the framework used by other interval problems (see the next section).

Sweep Line Technique

Sweep line is a general framework for interval problems. Convert each interval into two events (a start event and an end event), sort the events by position, and sweep through them while maintaining a running counter that tracks active intervals.

General Template

  1. For each interval [s, e], emit two events: (s, +1) and (e, -1).
  2. Sort events by position. Tie-breaking: end events (-1) typically come before start events (+1) at the same position to model half-open intervals; reverse the order for closed intervals.
  3. Sweep through events left to right. Maintain a counter. At each event, add the event's delta. The counter value represents the number of intervals active at that position.

For Meeting Rooms II, the answer is the maximum counter value reached during the sweep. The sort by (position, delta) produces the correct tie-breaking for half-open intervals because -1 < +1.

Implementation

Other Sweep Line Applications

The same event-counter pattern solves several related problems:

  • Skyline Problem (LC 218): sweep through building edges, maintaining a max-heap of active heights to compute the visible outline.
  • Employee Free Time (LC 759): flatten all employee schedules into events, sweep, and emit gaps where the counter drops to zero.
  • Interval List Intersections (LC 986): can be reframed as a sweep over two-pointer events on sorted lists.

The pattern is a useful mental tool when a problem asks "how many things are active at the busiest moment" or "what is the union/gap structure across many intervals".

Canonical Problem: Non-overlapping Intervals (LC 435)

Problem: given a list of intervals, return the minimum number of intervals to remove so that the remaining intervals are non-overlapping.

This is equivalent to the interval scheduling maximization problem: find the largest subset of intervals that do not overlap. The answer to the original problem is n - max_nonoverlapping.

Approach

Greedy by end time. Sort the intervals by end time. Iterate through the sorted list, greedily picking each interval whose start is greater than or equal to the last picked interval's end.

Exchange argument: any optimal schedule can be transformed into this greedy one without reducing the count, by swapping each picked interval with the earliest-ending compatible alternative. Picking the earliest-ending compatible interval leaves the most room for subsequent picks, which is why greedy-by-end is optimal here while greedy-by-start is not.

Walkthrough

Trace on [[1,2],[2,3],[3,4],[1,3]]:

  • Sort by end: [[1,2],[2,3],[1,3],[3,4]].
  • Pick [1,2]. lastEnd = 2. Kept = 1.
  • [2,3]: 2 >= 2, pick. lastEnd = 3. Kept = 2.
  • [1,3]: 1 < 3, skip.
  • [3,4]: 3 >= 3, pick. lastEnd = 4. Kept = 3.

Removed = 4 - 3 = 1.

Implementation

Time Complexity: O(n log n) for the sort, O(n) for the greedy pass.

Space Complexity: O(1) extra space beyond the input (O(log n) for the sort on most implementations).

Problem Variants

Interval problems come in several flavors, each mapped to a sorting strategy and an approach.

VariantSort ByApproachExample Problem
Merge overlappingStartExtend end if overlapping with previousMerge Intervals
Insert into sortedPre-sortedSplit into three regions: before, overlap, afterInsert Interval
Remove minimum overlappingEndGreedy: pick interval that ends earliestNon-overlapping Intervals
Count maximum concurrentEventsLine sweep: +1 at start, -1 at endMeeting Rooms II
Find gapsStartTrack last end, compare with next startMissing Ranges
Intersection of two listsTwo pointersAdvance pointer of interval that ends firstInterval List Intersections

When to Use Interval Techniques

Signs that you are facing an interval problem:

  • Input is a list of ranges, time slots, or start/end pairs
  • Problem mentions scheduling, booking, or resource allocation
  • You need to find overlaps, gaps, or merge ranges
  • The problem involves "covering" a range or "selecting" non-overlapping items

When these techniques might NOT apply:

  • Intervals have dependencies beyond just overlap (use graph algorithms)
  • You need to find all possible combinations (may need backtracking)
  • The problem involves weighted intervals with optimization (may need DP)
  • Intervals are on a 2D plane (different techniques entirely)

Example Walkthrough 1: Meeting Rooms I (LeetCode 252)

This problem uses basic overlap detection. Meeting Rooms uses half-open semantics: meeting [1,5] does not conflict with [5,8] because the rooms are released at the end time. The code below uses strict < to match this convention.

Problem: Given an array of meeting time intervals where intervals[i] = [start, end], determine if a person can attend all meetings.

Approach

If any two meetings overlap, return false. The brute force approach checks all pairs in O(n^2). But if we sort by start time, overlapping meetings become adjacent. We only need to check each meeting against the previous one.

After sorting by start time, meeting A overlaps with meeting B (where A comes before B) if and only if A's end time is greater than B's start time.

Implementation

Walkthrough

Time Complexity: O(n log n) for sorting, O(n) for the scan. Total: O(n log n).

Space Complexity: O(1) extra space (O(log n) for sorting in some implementations).

Example Walkthrough 2: Interval List Intersections (LeetCode 986)

This problem uses the two-pointer approach on two sorted interval lists.

Problem: Given two lists of closed intervals, each list is pairwise disjoint (no overlaps within a list) and sorted. Return the intersection of these two interval lists.

Approach

Use two pointers, one for each list. At each step:

  1. Check if current intervals overlap
  2. If they overlap, compute and record the intersection
  3. Advance the pointer whose interval ends first (since it cannot intersect with any further intervals from the other list)

The intersection of [a,b] and [c,d] (when they overlap) is:

Implementation

Walkthrough

Time Complexity: O(m + n) where m and n are the lengths of the two lists.

Space Complexity: O(m + n) for the output. O(1) auxiliary space if the output array is not counted as extra space.

Common Mistakes

Mistake 1: Forgetting to Sort

Many interval algorithms require sorted input. Forgetting to sort leads to incorrect results.

Mistake 2: Using Wrong Sort Key

Sorting by start time and end time are not interchangeable.

  • Merge intervals: Sort by start time
  • Select maximum non-overlapping: Sort by end time
  • Insert interval: Input is already sorted by start time

Mistake 3: Off-by-One in Overlap Detection

The difference between < and <= matters for whether touching intervals count as overlapping.

Read the problem carefully to determine the expected behavior.

Mistake 4: Forgetting the Last Interval

When building a result list incrementally, the last interval is often added inside the loop only under certain conditions. Make sure to add it after the loop.

Mistake 5: Modifying Input Array

Some problems pass the input by reference and expect the original array to remain unchanged after the function returns. This matters when the same input is reused across multiple test calls or when other code holds references to it. Creating a copy before sorting avoids this issue.

Quiz

Introduction to Intervals Quiz

10 quizzes