🧠
In-place Merge After Sorting
💡 This approach optimizes space by merging intervals in-place after sorting, reducing extra memory usage.
Intuition
Sort intervals by start time, then overwrite intervals array by merging overlapping intervals as you iterate, keeping track of the position to write merged intervals.
Algorithm
- Sort intervals by start time.
- Initialize a pointer to track position of last merged interval.
- Iterate over intervals starting from second interval:
- If current overlaps with last merged, merge by updating end.
- Else, move pointer forward and copy current interval.
💡 This approach is tricky because it modifies the input array directly, requiring careful pointer management.
def merge(intervals):
if not intervals:
return []
intervals.sort(key=lambda x: x[0])
index = 0
for i in range(1, len(intervals)):
if intervals[i][0] <= intervals[index][1]:
intervals[index][1] = max(intervals[index][1], intervals[i][1])
else:
index += 1
intervals[index] = intervals[i]
return intervals[:index+1]
# Driver code
if __name__ == '__main__':
intervals = [[1,3],[2,6],[8,10],[15,18]]
print(merge(intervals))
Line Notes
if not intervals:Handle empty input to avoid errors.
intervals.sort(key=lambda x: x[0])Sort intervals by start time for ordered processing.
index = 0Pointer to track last merged interval position.
for i in range(1, len(intervals))Iterate over intervals starting from second.
if intervals[i][0] <= intervals[index][1]:Check if current interval overlaps with last merged.
intervals[index][1] = max(intervals[index][1], intervals[i][1])Merge intervals in-place by updating end.
else: index += 1Move pointer forward for new non-overlapping interval.
intervals[index] = intervals[i]Copy current interval to merged position.
return intervals[:index+1]Return merged intervals slice up to last merged index.
import java.util.*;
public class MergeIntervals {
public static int[][] merge(int[][] intervals) {
if (intervals.length == 0) return new int[0][0];
Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
int index = 0;
for (int i = 1; i < intervals.length; i++) {
if (intervals[i][0] <= intervals[index][1]) {
intervals[index][1] = Math.max(intervals[index][1], intervals[i][1]);
} else {
index++;
intervals[index] = intervals[i];
}
}
return Arrays.copyOfRange(intervals, 0, index + 1);
}
public static void main(String[] args) {
int[][] intervals = {{1,3},{2,6},{8,10},{15,18}};
int[][] result = merge(intervals);
for (int[] interval : result) {
System.out.println("[" + interval[0] + "," + interval[1] + "]");
}
}
}
Line Notes
if (intervals.length == 0) return new int[0][0];Handle empty input to avoid errors.
Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));Sort intervals by start time for ordered processing.
int index = 0;Pointer to track last merged interval position.
for (int i = 1; i < intervals.length; i++) {Iterate over intervals starting from second.
if (intervals[i][0] <= intervals[index][1]) {Check if current interval overlaps with last merged.
intervals[index][1] = Math.max(intervals[index][1], intervals[i][1]);Merge intervals in-place by updating end.
else { index++; intervals[index] = intervals[i]; }Move pointer and copy new interval.
return Arrays.copyOfRange(intervals, 0, index + 1);Return merged intervals slice.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<vector<int>> merge(vector<vector<int>>& intervals) {
if (intervals.empty()) return {};
sort(intervals.begin(), intervals.end(), [](const vector<int>& a, const vector<int>& b) {
return a[0] < b[0];
});
int index = 0;
for (int i = 1; i < (int)intervals.size(); i++) {
if (intervals[i][0] <= intervals[index][1]) {
intervals[index][1] = max(intervals[index][1], intervals[i][1]);
} else {
index++;
intervals[index] = intervals[i];
}
}
intervals.resize(index + 1);
return intervals;
}
int main() {
vector<vector<int>> intervals = {{1,3},{2,6},{8,10},{15,18}};
vector<vector<int>> result = merge(intervals);
for (auto &interval : result) {
cout << "[" << interval[0] << "," << interval[1] << "]\n";
}
return 0;
}
Line Notes
if (intervals.empty()) return {};Handle empty input to avoid errors.
sort(intervals.begin(), intervals.end(), ...Sort intervals by start time for ordered processing.
int index = 0;Pointer to track last merged interval position.
for (int i = 1; i < (int)intervals.size(); i++) {Iterate over intervals starting from second.
if (intervals[i][0] <= intervals[index][1]) {Check if current interval overlaps with last merged.
intervals[index][1] = max(intervals[index][1], intervals[i][1]);Merge intervals in-place by updating end.
else { index++; intervals[index] = intervals[i]; }Move pointer and copy new interval.
intervals.resize(index + 1);Resize vector to keep only merged intervals.
function merge(intervals) {
if (intervals.length === 0) return [];
intervals.sort((a, b) => a[0] - b[0]);
let index = 0;
for (let i = 1; i < intervals.length; i++) {
if (intervals[i][0] <= intervals[index][1]) {
intervals[index][1] = Math.max(intervals[index][1], intervals[i][1]);
} else {
index++;
intervals[index] = intervals[i];
}
}
return intervals.slice(0, index + 1);
}
// Driver code
console.log(merge([[1,3],[2,6],[8,10],[15,18]]));
Line Notes
if (intervals.length === 0) return [];Handle empty input to avoid errors.
intervals.sort((a, b) => a[0] - b[0]);Sort intervals by start time for ordered processing.
let index = 0;Pointer to track last merged interval position.
for (let i = 1; i < intervals.length; i++) {Iterate over intervals starting from second.
if (intervals[i][0] <= intervals[index][1]) {Check if current interval overlaps with last merged.
intervals[index][1] = Math.max(intervals[index][1], intervals[i][1]);Merge intervals in-place by updating end.
else { index++; intervals[index] = intervals[i]; }Move pointer and copy new interval.
return intervals.slice(0, index + 1);Return merged intervals slice.
TimeO(n log n)
SpaceO(1) additional space
Sorting is O(n log n), merging is O(n). Space is optimized by modifying input in-place.
💡 For large n, this saves memory compared to creating new lists, important in memory-constrained environments.
Interview Verdict: Accepted / Space optimized
This approach is ideal when interviewers ask for in-place or space-efficient solutions.