
Problem Statement
The task is to process an array of intervals where each interval is defined by two integers representing its start and end. The objective is to merge all overlapping intervals into a minimal set of non-overlapping intervals that cover the same ranges as the input. Each interval in the input array is denoted as [starti, endi]
, wherein starti
is the start point of the interval, and endi
is the endpoint (inclusive). The merging of two overlapping intervals should result in a new interval that spans from the minimum start point to the maximum end point of the overlapping intervals.
Examples
Example 1
Input:
intervals = [[1,3],[2,6],[8,10],[15,18]]
Output:
[[1,6],[8,10],[15,18]]
Explanation:
Since intervals [1,3] and [2,6] overlap, merge them into [1,6].
Example 2
Input:
intervals = [[1,4],[4,5]]
Output:
[[1,5]]
Explanation:
Intervals [1,4] and [4,5] are considered overlapping.
Constraints
1 <= intervals.length <= 104
intervals[i].length == 2
0 <= starti <= endi <= 104
Approach and Intuition
The goal here is to combine all intervals that have an intersection to create the broadest possible intervals without any overlaps except at the boundaries where they touch.
Steps to achieve the solution:
Sort the Intervals: Start by sorting the intervals based on their start times. Sorting makes it easier to merge overlapping intervals in a single pass through the sorted list.
Initialize with the First Interval: Begin with the first interval as the base for comparison.
Iterate and Merge: Iterate through the intervals, and for each one:
- Compare the current interval with the last merged interval in your result list (beginning with the very first interval if the list is still empty).
- If the current interval starts after the end of the last merged interval, it does not overlap, and you can safely add it to the list of merged intervals.
- If there is an overlap (i.e., the current interval starts before or exactly when the last merged interval ends), merge them. This merging is done by updating the end of the last merged interval to the maximum of its own end and the end of the current interval.
Insights from the Examples:
- In the first example, intervals
[1,3]
and[2,6]
overlap because the start of the second interval falls between the start and end of the first. After merging, they form[1,6]
, which does not overlap with the later intervals[8,10]
and[15,18]
, each added as they appear. - In the second example, the fact that intervals
[1,4]
and[4,5]
touch at the boundary indicates an overlap as per problem statement guidelines, thus they merge into a single interval[1,5]
.
This approach ensures that overlapping intervals are combined into the minimum possible number of contiguous intervals, which is achieved efficiently with a time complexity primarily dictated by the sorting step, i.e., O(n log n)
where n
is the number of intervals.
Solutions
- C++
- Java
- C
- JavaScript
- Python
class Solution {
public:
vector<vector<int>> combine(vector<vector<int>>& segments) {
sort(segments.begin(), segments.end());
vector<vector<int>> combinedSegments;
for (auto seg : segments) {
if (combinedSegments.empty() || combinedSegments.back()[1] < seg[0]) {
combinedSegments.push_back(seg);
}
else {
combinedSegments.back()[1] = max(combinedSegments.back()[1], seg[1]);
}
}
return combinedSegments;
}
};
This C++ solution addresses the problem of merging overlapping intervals. The code defines a class Solution
with a member function combine
that accepts a vector of vector integers representing segments and returns a vector of combined intervals.
- Start by sorting the
segments
vector based on the starting times of intervals to organize them in ascending order. - Initialize a new vector called
combinedSegments
to store the merged intervals. - Iterate through the sorted segments:
- If
combinedSegments
is empty or the last added interval does not overlap with the current interval (seg
), addseg
directly tocombinedSegments
. - If the last interval in
combinedSegments
overlaps withseg
(the end of the last interval is greater than or equal to the start ofseg
), merge them by extending the end of the last interval incombinedSegments
to the maximum end of both intervals.
- If
- Finally, return
combinedSegments
containing the merged intervals.
By following this approach, the program efficiently merges all overlapping intervals into minimal disjoint intervals.
class Solution {
public int[][] mergeIntervals(int[][] intervals) {
Arrays.sort(intervals, (x, y) -> Integer.compare(x[0], y[0]));
LinkedList<int[]> mergedList = new LinkedList<>();
for (int[] range : intervals) {
if (mergedList.isEmpty() || mergedList.getLast()[1] < range[0]) {
mergedList.add(range);
} else {
mergedList.getLast()[1] = Math.max(mergedList.getLast()[1], range[1]);
}
}
return mergedList.toArray(new int[mergedList.size()][]);
}
}
The provided Java solution for merging overlapping intervals involves sorting the interval list and using a LinkedList to hold the merged intervals efficiently. Below is a comprehensive step-by-step approach to understand the solution:
Sort the array of intervals based on the starting times. This ensures that any intervals which might need to be merged are adjacent in the array, making it easier to merge them in a single pass.
Initialize a LinkedList named
mergedList
to store the merged intervals. LinkedList is preferred here for dynamic addition and efficient retrieval of the last element.Iterate through each interval in the sorted array:
- If
mergedList
is empty or if the last interval inmergedList
does not overlap with the current interval (i.e., the end of the last interval inmergedList
is less than the start of the current interval), simply add the current interval tomergedList
. - If there is an overlap (the end of the last interval in
mergedList
is greater than or equal to the start of the current interval), merge the current interval with the last interval inmergedList
. This is done by updating the end of the last interval inmergedList
to be the maximum of its own end and the end of the current interval.
- If
Convert
mergedList
back to a 2D array to match the expected return type of the function.
This method ensures an optimal approach to the merge intervals problem by reducing unnecessary comparisons and making efficient use of data structures to handle the intervals dynamically.
int minimum(int x, int y) { return x < y ? x : y; }
int maximum(int x, int y) { return x > y ? x : y; }
int customCompare(const void* x, const void* y) {
int* ix = *(int**)x;
int* iy = *(int**)y;
return ix[0] == iy[0] ? iy[1] - ix[1] : ix[0] - iy[0];
}
int** combineIntervals(int** intervals, int size, const int* colSize,
int* outSize, int** outColSizes) {
int count = size;
if (count == 0) {
*outSize = 0;
return NULL;
}
qsort(intervals, count, sizeof(int*), customCompare);
int** combined = malloc(sizeof(int*) * count);
for (int i = 0; i < count; ++i) combined[i] = malloc(sizeof(int) * 2);
memcpy(combined[0], intervals[0], 2 * sizeof(int));
int idx = 0; // track the last index in the combined array
for (int i = 1; i < count; ++i) {
int start = intervals[i][0], end = intervals[i][1];
if (start <= combined[idx][1]) {
combined[idx][1] = maximum(combined[idx][1], end);
} else {
memcpy(combined[++idx], intervals[i], 2 * sizeof(int));
}
}
++idx;
*outSize = idx;
*outColSizes = malloc(sizeof(int) * idx);
for (int i = 0; i < idx; ++i) {
(*outColSizes)[i] = 2;
}
return combined;
}
This summary explains the solution to the problem of merging overlapping intervals using C programming language.
The provided code defines several functions for handling, comparing, and merging intervals:
minimum and maximum functions are utility functions used for returning the lesser and greater of two integers, respectively, ensuring correct interval boundaries during merging.
customCompare function is defined to help in sorting the intervals. It makes use of the
qsort
standard function's capability by providing it a way to compare intervals primarily by their starting points. If starting points are the same, it sorts by ending points.combineIntervals is the principal function that handles the logic of merging intervals. It starts by handling the base case—returning
NULL
if no intervals are present. Intervals are then sorted usingqsort
withcustomCompare
.After sorting, memory is allocated dynamically for storing merged intervals. The merging happens in a loop; if the current interval's start time is less than or equal to the previously stored interval's end time, the intervals overlap and are merged by adjusting the end time to the maximum of the two end times. If they do not overlap, the interval is added to the result as a new non-overlapping interval.
The end of this process updates the output count and adjusts output column sizes to reflect pairs of integers (start and end times for each interval).
In summary, the solution involves sorting the intervals based on their start (and conditionally end) times, then merging overlapping intervals iteratively, storing the result in dynamically allocated memory, and finally outputting the merged intervals and their count. This method ensures efficient handling of potentially large sets of intervals with overlapping times.
var combineIntervals = function (ranges) {
ranges.sort((first, second) => first[0] - second[0]);
let combined = [];
for (let range of ranges) {
if (combined.length === 0 || combined[combined.length - 1][1] < range[0]) {
combined.push(range);
} else {
combined[combined.length - 1][1] = Math.max(
combined[combined.length - 1][1],
range[1],
);
}
}
return combined;
};
The solution provided addresses the problem of merging overlapping intervals. The JavaScript function combineIntervals
takes an array of intervals as an argument, where each interval is represented as a two-element array. The function merges all overlapping intervals and returns the merged intervals as an array. Here's how the solution works:
- The intervals are first sorted based on their starting points to simplify the merging process.
- Initialize an empty array
combined
to store the merged intervals. - Iterate through each interval in the sorted array:
- If the
combined
array is empty or if the last interval incombined
does not overlap with the current interval, simply add the current interval tocombined
. - If there is an overlap, merge the current interval with the last interval in
combined
by updating the end point of the last interval to be the maximum of the end points of the last interval incombined
and the current interval.
- If the
- Finally, return the
combined
array containing all the merged intervals.
This approach ensures that all overlapping intervals are merged into a minimal set of intervals.
class Solution:
def merge_intervals(self, ranges: List[List[int]]) -> List[List[int]]:
# First, sort the ranges based on the starting values of each interval.
ranges.sort(key=lambda interval: interval[0])
# Initialize an empty list to store the merged intervals
combined_intervals = []
for current_interval in ranges:
# Check if the combined_intervals list is empty or if the last interval does not overlap with current one
if not combined_intervals or combined_intervals[-1][1] < current_interval[0]:
combined_intervals.append(current_interval)
else:
# There is an overlap, so we merge the current interval with the last one in the list
combined_intervals[-1][1] = max(combined_intervals[-1][1], current_interval[1])
return combined_intervals
The solution implements a function to merge overlapping intervals given a list of interval ranges. Follow these steps to understand the process executed by the Python code:
Sorts the intervals by their start times to ensure they are in order and easier to compare.
Initializes an empty list
combined_intervals
to store the merged intervals.Iterates through the sorted
ranges
. For eachcurrent_interval
:- Checks if
combined_intervals
is empty or if the last interval incombined_intervals
does not overlap withcurrent_interval
. If true, appendscurrent_interval
tocombined_intervals
. - If there is an overlap (meaning the end of the last interval in
combined_intervals
is greater than or equal to the start ofcurrent_interval
), merges the intervals by updating the end of the last interval incombined_intervals
to be the maximum end value of both overlapping intervals.
- Checks if
Finally, the function returns the
combined_intervals
which contains all the merged intervals.
This approach ensures that all overlapping intervals are combined into single intervals, and non-overlapping intervals are appended as distinct entries. The resultant list provides merged ranges in a minimal set.
No comments yet.