Sort and Merge
Intuition
The key insight is that once we sort the intervals by their start time, overlapping intervals will be adjacent. We iterate through the sorted intervals and compare each interval with the last interval in our result list. If they overlap (current start <= previous end), we merge them by extending the previous interval's end to the maximum of both ends. If they don't overlap, we start a new interval. This greedy approach works because sorting ensures we process intervals in order and never need to look back more than one step.
Algorithm
- Sort the intervals by their start time.
- Initialize a result list with the first interval.
- For each subsequent interval, compare it with the last interval in the result.
- If the current interval's start is less than or equal to the last result interval's end, they overlap. Update the last result interval's end to the maximum of both ends.
- Otherwise, add the current interval as a new entry in the result.
- Return the result list.
O(n log n)SpaceO(n)Code (C++ · Java · Python · Go)
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end());
vector<vector<int>> result;
for (auto& interval : intervals) {
if (result.empty() || result.back()[1] < interval[0]) {
result.push_back(interval);
} else {
result.back()[1] = max(result.back()[1], interval[1]);
}
}
return result;
}
};class Solution {
public int[][] merge(int[][] intervals) {
Arrays.sort(intervals, (a, b) -> a[0] - b[0]);
List<int[]> result = new ArrayList<>();
for (int[] interval : intervals) {
if (result.isEmpty() || result.get(result.size() - 1)[1] < interval[0]) {
result.add(interval);
} else {
result.get(result.size() - 1)[1] = Math.max(
result.get(result.size() - 1)[1], interval[1]
);
}
}
return result.toArray(new int[result.size()][]);
}
}def merge(intervals: List[List[int]]) -> List[List[int]]:
intervals.sort()
result = []
for interval in intervals:
if not result or result[-1][1] < interval[0]:
result.append(interval)
else:
result[-1][1] = max(result[-1][1], interval[1])
return resultimport "sort"
func merge(intervals [][]int) [][]int {
sort.Slice(intervals, func(i, j int) bool {
return intervals[i][0] < intervals[j][0]
})
result := [][]int{}
for _, interval := range intervals {
if len(result) == 0 || result[len(result)-1][1] < interval[0] {
result = append(result, interval)
} else {
if interval[1] > result[len(result)-1][1] {
result[len(result)-1][1] = interval[1]
}
}
}
return result
}