Merge Intervals
Medium · Intervals · Explanation and code example
Greedy
How it works
We want to merge all overlapping intervals so the result contains only non-overlapping ranges.
This solution uses a greedy idea with an auxiliary array:
- For every possible start point
start, we record the farthest end of any interval that begins atstart - Then we scan from left to right, maintaining the farthest point we must still cover (
have)
While scanning:
- if we see an interval starting at position
i, we may need to extend our current merged interval’s end to include it - once our scan index reaches the farthest required end, we can safely close the current merged interval
So the scan behaves like:
- “start a merged interval when we first see coverage”
- “keep extending its end while overlaps exist”
- “close it when we finish the coverage”
Steps
- Find the maximum start value among all intervals (
max_val). - Create an array
mpof sizemax_val + 1:mp[start]will store the farthest(end + 1)among intervals that start atstart
- For each interval
[start, end]:- update
mp[start] = max(mp[start], end + 1)
- update
- Initialize:
resas an empty list for merged intervalsinterval_start = -1to mark the start of the current merged intervalhave = -1to track the farthest end of the current merged interval
- Scan
ifrom0tolen(mp) - 1:- If
mp[i] != 0, it means some interval starts ati:- if we are not already in a merged interval, set
interval_start = i - update
have = max(have, mp[i] - 1)(convert back to real end)
- if we are not already in a merged interval, set
- If
have == i, it means we reached the end of the current merged interval:- append
[interval_start, have]tores - reset
interval_startandhave
- append
- If
- After the scan, if a merged interval is still open, append it to
res. - Return
res.
Complexity
- Time complexity:
O(n + m) - Space complexity:
O(n)
Where
nis the length of the array andmis the maximum start value among all the intervals.
Things to watch for
Using Strict Inequality for Overlap Check
Two intervals overlap when current.start <= last.end, not <. Intervals [1, 3] and [3, 5] are considered overlapping and should merge to [1, 5].
Forgetting to Update the End When Merging
When merging overlapping intervals, the new end should be max(last.end, current.end), not just current.end. An earlier interval might extend further than a later-starting one.
Not Sorting Before Processing
The sorting approach assumes intervals are processed in order of start time. Without sorting, you cannot guarantee that overlapping intervals are adjacent, leading to missed merges.
Python code example
from typing import List
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
max_val = max(interval[0] for interval in intervals)
mp = [0] * (max_val + 1)
for start, end in intervals:
mp[start] = max(end + 1, mp[start])
res = []
have = -1
interval_start = -1
for i in range(len(mp)):
if mp[i] != 0:
if interval_start == -1:
interval_start = i
have = max(mp[i] - 1, have)
if have == i:
res.append([interval_start, have])
have = -1
interval_start = -1
if interval_start != -1:
res.append([interval_start, have])
return res
C++ code example
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
int max_val = 0;
for (const auto& interval : intervals) {
max_val = max(interval[0], max_val);
}
vector<int> mp(max_val + 1, 0);
for (const auto& interval : intervals) {
int start = interval[0];
int end = interval[1];
mp[start] = max(end + 1, mp[start]);
}
vector<vector<int>> res;
int have = -1;
int intervalStart = -1;
for (int i = 0; i < mp.size(); i++) {
if (mp[i] != 0) {
if (intervalStart == -1) intervalStart = i;
have = max(mp[i] - 1, have);
}
if (have == i) {
res.push_back({intervalStart, have});
have = -1;
intervalStart = -1;
}
}
if (intervalStart != -1) {
res.push_back({intervalStart, have});
}
return res;
}
};
Source and license
Adapted from NeetCode’s source · MIT license. Node types are supplied by LeetCode where needed.