Step 1 Understand it
Remember it by
Sort by start, then compare each interval with the last one you kept.
Watch it happen
Read the animation as text
- Can one person attend every meeting? Only if no two meetings overlap.
- Sort by start time. Then any clash must be between neighbours in the sorted order, so one pass of neighbour checks is enough.
- [0, 30] then [5, 10]: the second starts at 5, before the first ends at 30 (5 < 30). A clash: answer False.
- 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 --> NAnalogy
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]]
- Sort by start: Already sorted [[1,3], [2,6], [8,10]].
- Add [1,3] to our answer list.
- 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]].
- 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.
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 mergedThe same template in Java
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()][]);
}
}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]]
| meeting | next meeting | clash? |
|---|---|---|
| [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.
def can_attend_meetings(intervals):
intervals.sort()
for (s1, e1), (s2, e2) in zip(intervals, intervals[1:]):
if s2 < e1:
return False
return TrueMedium example: Merge Intervals
Input: intervals = [[1, 3], [8, 10], [2, 6], [15, 18]]
| interval (sorted order) | decision | merged 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.
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 mergedStep 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
-
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
-
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.
-
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.
-
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.
-
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
-
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).