Welcome to Subscribe On Youtube
56. Merge Intervals
Description
Given an array of intervals
where intervals[i] = [starti, endi]
, merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input.
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
Solutions
Solution 1: Sorting + One-pass Traversal
We can sort the intervals in ascending order by the left endpoint, and then traverse the intervals for merging operations.
The specific merging operation is as follows.
First, we add the first interval to the answer. Then, we consider each subsequent interval in turn:
- If the right endpoint of the last interval in the answer array is less than the left endpoint of the current interval, it means that the two intervals will not overlap, so we can directly add the current interval to the end of the answer array;
- Otherwise, it means that the two intervals overlap. We need to use the right endpoint of the current interval to update the right endpoint of the last interval in the answer array, setting it to the larger of the two.
Finally, we return the answer array.
The time complexity is $O(n \times \log n)$, and the space complexity is $O(\log n)$. Here, $n$ is the number of intervals.
Example Input
Consider the following list of intervals: [[1,3],[2,6],[8,10],[15,18]]
. These intervals represent parts of a line with start and end points.
-
Sort Intervals: First, the code sorts the intervals based on their start values. For our example, the intervals are already sorted, so the sorted list remains
[[1,3],[2,6],[8,10],[15,18]]
. -
Initialization: An empty list
ans
is initialized to store the merged intervals. -
Iteration and Merging:
- The code iterates through the sorted intervals.
- For the first interval
[1,3]
,ans
is empty, so the interval is directly appended toans
. - Next interval,
[2,6]
, overlaps with[1,3]
since3 >= 2
. So, we merge them by updating the end of the last interval inans
tomax(3, 6) = 6
. Now,ans = [[1,6]]
. - The next interval
[8,10]
does not overlap with[1,6]
because6 < 8
. So,[8,10]
is appended toans
, resulting inans = [[1,6], [8,10]]
. - Similarly,
[15,18]
doesn’t overlap with the last interval inans
([8,10]
), so it’s also appended toans
. The finalans
is[[1,6], [8,10], [15,18]]
.
The function returns the merged intervals: [[1,6],[8,10],[15,18]]
. This means we have three ranges where the intervals overlap or are continuous without gaps.
-
class Solution { public int[][] merge(int[][] intervals) { Arrays.sort(intervals, (a, b) -> a[0] - b[0]); List<int[]> ans = new ArrayList<>(); ans.add(intervals[0]); for (int i = 1; i < intervals.length; ++i) { int s = intervals[i][0], e = intervals[i][1]; if (ans.get(ans.size() - 1)[1] < s) { ans.add(intervals[i]); } else { ans.get(ans.size() - 1)[1] = Math.max(ans.get(ans.size() - 1)[1], e); } } return ans.toArray(new int[ans.size()][]); } }
-
class Solution { public: vector<vector<int>> merge(vector<vector<int>>& intervals) { sort(intervals.begin(), intervals.end()); vector<vector<int>> ans; ans.emplace_back(intervals[0]); for (int i = 1; i < intervals.size(); ++i) { if (ans.back()[1] < intervals[i][0]) { ans.emplace_back(intervals[i]); } else { ans.back()[1] = max(ans.back()[1], intervals[i][1]); } } return ans; } };
-
# Definition for an interval. # class Interval(object): # def __init__(self, s=0, e=0): # self.start = s # self.end = e class Solution(object): def merge(self, intervals): """ :type intervals: List[Interval] :rtype: List[Interval] """ ans = [] for intv in sorted(intervals, key=lambda x: x.start): if ans and ans[-1].end >= intv.start: ans[-1].end = max(ans[-1].end, intv.end) else: ans.append(intv) return ans ###### ''' >>> intervals = [[111,222],[1,3],[2,6],[8,10],[15,18]] >>> intervals.sort() >>> intervals [[1, 3], [2, 6], [8, 10], [15, 18], [111, 222]] ''' class Solution: def merge(self, intervals: List[List[int]]) -> List[List[int]]: intervals.sort() # default sort also ok ans = [intervals[0]] for s, e in intervals[1:]: if ans[-1][1] < s: ans.append([s, e]) else: ans[-1][1] = max(ans[-1][1], e) return ans
-
func merge(intervals [][]int) (ans [][]int) { sort.Slice(intervals, func(i, j int) bool { return intervals[i][0] < intervals[j][0] }) ans = append(ans, intervals[0]) for _, e := range intervals[1:] { if ans[len(ans)-1][1] < e[0] { ans = append(ans, e) } else { ans[len(ans)-1][1] = max(ans[len(ans)-1][1], e[1]) } } return }
-
function merge(intervals: number[][]): number[][] { intervals.sort((a, b) => a[0] - b[0]); const ans: number[][] = [intervals[0]]; for (let i = 1; i < intervals.length; ++i) { if (ans.at(-1)[1] < intervals[i][0]) { ans.push(intervals[i]); } else { ans.at(-1)[1] = Math.max(ans.at(-1)[1], intervals[i][1]); } } return ans; }
-
public class Solution { public int[][] Merge(int[][] intervals) { intervals = intervals.OrderBy(a => a[0]).ToArray(); var ans = new List<int[]>(); ans.Add(intervals[0]); for (int i = 1; i < intervals.Length; ++i) { if (ans[ans.Count - 1][1] < intervals[i][0]) { ans.Add(intervals[i]); } else { ans[ans.Count - 1][1] = Math.Max(ans[ans.Count - 1][1], intervals[i][1]); } } return ans.ToArray(); } }
-
impl Solution { pub fn merge(mut intervals: Vec<Vec<i32>>) -> Vec<Vec<i32>> { intervals.sort_unstable_by(|a, b| a[0].cmp(&b[0])); let n = intervals.len(); let mut res = vec![]; let mut i = 0; while i < n { let l = intervals[i][0]; let mut r = intervals[i][1]; i += 1; while i < n && r >= intervals[i][0] { r = r.max(intervals[i][1]); i += 1; } res.push(vec![l, r]); } res } }
-
/** * @param {number[][]} intervals * @return {number[][]} */ var merge = function (intervals) { intervals.sort((a, b) => a[0] - b[0]); const result = []; const n = intervals.length; let i = 0; while (i < n) { const left = intervals[i][0]; let right = intervals[i][1]; while (true) { i++; if (i < n && right >= intervals[i][0]) { right = Math.max(right, intervals[i][1]); } else { result.push([left, right]); break; } } } return result; };