Merge Overlapping Intervals
Last Updated :
19 Oct, 2023
Given a set of time intervals in any order, our task is to merge all overlapping intervals into one and output the result which should have only mutually exclusive intervals.
Example:
Input: Intervals = {{1,3},{2,4},{6,8},{9,10}}
Output: {{1, 4}, {6, 8}, {9, 10}}
Explanation: Given intervals: [1,3],[2,4],[6,8],[9,10], we have only two overlapping intervals here,[1,3] and [2,4]. Therefore we will merge these two and return [1,4],[6,8], [9,10].
Input: Intervals = {{6,8},{1,9},{2,4},{4,7}}
Output: {{1, 9}}
Brute Force Approach:
A simple approach is to start from the first interval and compare it with all other intervals for overlapping, if it overlaps with any other interval, then remove the other interval from the list and merge the other into the first interval. Repeat the same steps for the remaining intervals after the first. This approach cannot be implemented in better than O(n^2) time.
Merge Overlapping Intervals using Sorting (Optimized Approach):
To solve this problem optimally we have to first sort the intervals according to the starting time. Once we have the sorted intervals, we can combine all intervals in a linear traversal. The idea is, in sorted array of intervals, if interval[i] doesn’t overlap with interval[i-1], then interval[i+1] cannot overlap with interval[i-1] because starting time of interval[i+1] must be greater than or equal to interval[i].
Follow the steps mentioned below to implement the approach:
- Sort the intervals based on the increasing order of starting time.
- Push the first interval into a stack.
- For each interval do the following:
- If the current interval does not overlap with the top of the stack then, push the current interval into the stack.
- If the current interval overlap with the top of the stack then, update the stack top with the ending time of the current interval.
- The end stack contains the merged intervals.
Below is the implementation of the above approach:
C++
#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;
vector<vector< int >> overlappedInterval(vector<vector< int >>& intervals) {
if (intervals.empty()) {
return vector<vector< int >>();
}
sort(intervals.begin(), intervals.end(), []( const vector< int >& a, const vector< int >& b) {
return a[0] < b[0];
});
stack<vector< int >> mergedStack;
mergedStack.push(intervals[0]);
for ( int i = 1; i < intervals.size(); i++) {
vector< int > current = intervals[i];
vector< int >& top = mergedStack.top();
if (current[0] <= top[1]) {
top[1] = max(top[1], current[1]);
} else {
mergedStack.push(current);
}
}
vector<vector< int >> mergedIntervals;
while (!mergedStack.empty()) {
mergedIntervals.insert(mergedIntervals.begin(), mergedStack.top());
mergedStack.pop();
}
return mergedIntervals;
}
int main() {
vector<vector< int >> intervals = {{6, 8}, {1, 9}, {2, 4}, {4, 7}};
vector<vector< int >> merged = overlappedInterval(intervals);
cout << "The Merged Intervals are: " ;
for ( const vector< int >& interval : merged) {
cout << "[" << interval[0] << ", " << interval[1] << "] " ;
}
cout << endl;
return 0;
}
|
Java
import java.util.Arrays;
import java.util.Comparator;
import java.util.Stack;
public class MergeOverlappingIntervals {
public static void mergeIntervals(Interval arr[])
{
if (arr.length <= 0 )
return ;
Stack<Interval> stack = new Stack<>();
Arrays.sort(arr, new Comparator<Interval>() {
public int compare(Interval i1, Interval i2)
{
return i1.start - i2.start;
}
});
stack.push(arr[ 0 ]);
for ( int i = 1 ; i < arr.length; i++) {
Interval top = stack.peek();
if (top.end < arr[i].start)
stack.push(arr[i]);
else if (top.end < arr[i].end) {
top.end = arr[i].end;
stack.pop();
stack.push(top);
}
}
System.out.print( "The Merged Intervals are: " );
while (!stack.isEmpty()) {
Interval t = stack.pop();
System.out.print( "[" + t.start + "," + t.end
+ "] " );
}
}
public static void main(String args[])
{
Interval arr[] = new Interval[ 4 ];
arr[ 0 ] = new Interval( 6 , 8 );
arr[ 1 ] = new Interval( 1 , 9 );
arr[ 2 ] = new Interval( 2 , 4 );
arr[ 3 ] = new Interval( 4 , 7 );
mergeIntervals(arr);
}
}
class Interval {
int start, end;
Interval( int start, int end)
{
this .start = start;
this .end = end;
}
}
|
Python3
def mergeIntervals(intervals):
intervals.sort()
stack = []
stack.append(intervals[ 0 ])
for i in intervals[ 1 :]:
if stack[ - 1 ][ 0 ] < = i[ 0 ] < = stack[ - 1 ][ - 1 ]:
stack[ - 1 ][ - 1 ] = max (stack[ - 1 ][ - 1 ], i[ - 1 ])
else :
stack.append(i)
print ( "The Merged Intervals are :" , end = " " )
for i in range ( len (stack)):
print (stack[i], end = " " )
arr = [[ 6 , 8 ], [ 1 , 9 ], [ 2 , 4 ], [ 4 , 7 ]]
mergeIntervals(arr)
|
C#
using System;
using System.Collections;
using System.Collections.Generic;
public class MergeOverlappingIntervals {
class sortHelper : IComparer {
int IComparer.Compare( object a, object b)
{
Interval first = (Interval)a;
Interval second = (Interval)b;
if (first.start == second.start) {
return first.end - second.end;
}
return first.start - second.start;
}
}
public static void mergeIntervals(Interval[] arr)
{
if (arr.Length <= 0)
return ;
Array.Sort(arr, new sortHelper());
Stack stack = new Stack();
stack.Push(arr[0]);
for ( int i = 1; i < arr.Length; i++) {
Interval top = (Interval)stack.Peek();
if (top.end < arr[i].start)
stack.Push(arr[i]);
else if (top.end < arr[i].end) {
top.end = arr[i].end;
stack.Pop();
stack.Push(top);
}
}
Console.Write( "The Merged Intervals are: " );
while (stack.Count != 0) {
Interval t = (Interval)stack.Pop();
Console.Write( "[" + t.start + "," + t.end
+ "] " );
}
}
public static void Main()
{
Interval[] arr = new Interval[4];
arr[0] = new Interval(6, 8);
arr[1] = new Interval(1, 9);
arr[2] = new Interval(2, 4);
arr[3] = new Interval(4, 7);
mergeIntervals(arr);
}
}
public class Interval {
public int start, end;
public Interval( int start, int end)
{
this .start = start;
this .end = end;
}
}
|
Javascript
class Interval {
constructor(start, end) {
this .start = start;
this .end = end;
}
}
function compareInterval(i1, i2) {
return (i1.start < i2.start);
}
function mergeIntervals(arr) {
if (arr.length <= 0)
return ;
let s = [];
arr.sort(compareInterval);
s.push(arr[0]);
for (let i = 1; i < arr.length; i++) {
let top = s[s.length-1];
if (top.end < arr[i].start)
s.push(arr[i]);
else if (top.end < arr[i].end) {
top.end = arr[i].end;
s.pop();
s.push(top);
}
}
console.log( "The Merged Intervals are: " );
while (s.length > 0) {
let t = s.pop();
console.log( "[" + t.start + "," + t.end + "] " );
}
return ;
}
let arr = [ new Interval(6,8), new Interval(1,9), new Interval(2,4), new Interval(4,7)];
mergeIntervals(arr);
|
Output
The Merged Intervals are: [1, 9]
Time complexity: O(N*log(N))
Auxiliary Space: O(N)
Merge Overlapping Intervals using Sorting (Space Optimized):
The above solution requires O(n) extra space for the stack. We can avoid the use of extra space by doing merge operations in place. Below are detailed steps.
Follow the steps mentioned below to implement the approach:
- Sort all intervals in increasing order of start time.
- Traverse sorted intervals starting from the first interval,
- Do the following for every interval.
- If the current interval is not the first interval and it overlaps with the previous interval,
then merge it with the previous interval. Keep doing it while the interval overlaps with the previous one.
- Otherwise, Add the current interval to the output list of intervals.
Below is the implementation of the above approach:
C++14
#include <bits/stdc++.h>
using namespace std;
struct Interval {
int s, e;
};
bool mycomp(Interval a, Interval b) { return a.s < b.s; }
void mergeIntervals(Interval arr[], int n)
{
sort(arr, arr + n, mycomp);
int index = 0;
for ( int i = 1; i < n; i++) {
if (arr[index].e >= arr[i].s) {
arr[index].e = max(arr[index].e, arr[i].e);
}
else {
index++;
arr[index] = arr[i];
}
}
cout << "\n The Merged Intervals are: " ;
for ( int i = 0; i <= index; i++)
cout << "[" << arr[i].s << ", " << arr[i].e << "] " ;
}
int main()
{
Interval arr[]
= { { 6, 8 }, { 1, 9 }, { 2, 4 }, { 4, 7 } };
int n = sizeof (arr) / sizeof (arr[0]);
mergeIntervals(arr, n);
return 0;
}
|
C
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct Interval {
int s, e;
} Interval;
int mycomp( const void * a, const void * b)
{
Interval* data_1 = (Interval*)a;
Interval* data_2 = (Interval*)b;
return (data_1->s - data_2->s);
}
int max( int num1, int num2)
{
return (num1 > num2) ? num1 : num2;
}
void mergeIntervals(Interval arr[], int n)
{
qsort (arr, n, sizeof (Interval), mycomp);
int index = 0;
for ( int i = 1; i < n; i++) {
if (arr[index].e >= arr[i].s) {
arr[index].e = max(arr[index].e, arr[i].e);
}
else {
index++;
arr[index] = arr[i];
}
}
printf ( "\n The Merged Intervals are: " );
for ( int i = 0; i <= index; i++)
printf ( "[%d, %d]" , arr[i].s, arr[i].e);
}
int main()
{
Interval arr[]
= { { 6, 8 }, { 1, 9 }, { 2, 4 }, { 4, 7 } };
int n = sizeof (arr) / sizeof (arr[0]);
mergeIntervals(arr, n);
return 0;
}
|
Java
import java.util.Arrays;
import java.util.Comparator;
class Interval {
int start, end;
Interval( int start, int end)
{
this .start = start;
this .end = end;
}
}
public class MergeOverlappingIntervals {
public static void mergeIntervals(Interval arr[])
{
Arrays.sort(arr, new Comparator<Interval>() {
public int compare(Interval i1, Interval i2)
{
return i1.start - i2.start;
}
});
int index = 0 ;
for ( int i = 1 ; i < arr.length; i++) {
if (arr[index].end >= arr[i].start) {
arr[index].end
= Math.max(arr[index].end, arr[i].end);
}
else {
index++;
arr[index] = arr[i];
}
}
System.out.print( "The Merged Intervals are: " );
for ( int i = 0 ; i <= index; i++) {
System.out.print( "[" + arr[i].start + ","
+ arr[i].end + "]" );
}
}
public static void main(String args[])
{
Interval arr[] = new Interval[ 4 ];
arr[ 0 ] = new Interval( 6 , 8 );
arr[ 1 ] = new Interval( 1 , 9 );
arr[ 2 ] = new Interval( 2 , 4 );
arr[ 3 ] = new Interval( 4 , 7 );
mergeIntervals(arr);
}
}
|
Python3
def mergeIntervals(arr):
arr.sort(key = lambda x: x[ 0 ])
index = 0
for i in range ( 1 , len (arr)):
if (arr[index][ 1 ] > = arr[i][ 0 ]):
arr[index][ 1 ] = max (arr[index][ 1 ], arr[i][ 1 ])
else :
index = index + 1
arr[index] = arr[i]
print ( "The Merged Intervals are :" , end = " " )
for i in range (index + 1 ):
print (arr[i], end = " " )
arr = [[ 6 , 8 ], [ 1 , 9 ], [ 2 , 4 ], [ 4 , 7 ]]
mergeIntervals(arr)
|
C#
using System;
using System.Linq;
class Interval {
public int start, end;
public Interval( int start, int end)
{
this .start = start;
this .end = end;
}
}
class MergeOverlappingIntervals {
public static void MergeIntervals(Interval[] arr)
{
arr = arr.OrderBy(x = > x.start).ToArray();
int index = 0;
for ( int i = 1; i < arr.Length; i++) {
if (arr[index].end >= arr[i].start) {
arr[index].end
= Math.Max(arr[index].end, arr[i].end);
}
else {
index++;
arr[index] = arr[i];
}
}
Console.WriteLine( "The Merged Intervals are: " );
for ( int i = 0; i <= index; i++) {
Console.WriteLine( "[" + arr[i].start + ","
+ arr[i].end + "]" );
}
}
public static void Main( string [] args)
{
Interval[] arr = new Interval[4];
arr[0] = new Interval(6, 8);
arr[1] = new Interval(1, 9);
arr[2] = new Interval(2, 4);
arr[3] = new Interval(4, 7);
MergeIntervals(arr);
}
}
|
Javascript
class Interval {
constructor(s, e) {
this .s = s;
this .e = e;
}
}
function mycomp(a, b) {
return a.s < b.s;
}
function mergeIntervals(arr) {
arr.sort(mycomp);
let index = 0;
for (let i = 1; i < arr.length; i++) {
if (arr[index].e >= arr[i].s) {
arr[index].e = Math.max(arr[index].e, arr[i].e);
}
else {
index++;
arr[index] = arr[i];
}
}
console.log( "\n The Merged Intervals are: " );
for (let i = 0; i <= index; i++)
console.log( "[" + arr[i].s + ", " + arr[i].e + "] " );
}
let arr = [ new Interval(6,8), new Interval(1,9), new Interval(2,4), new Interval(4,7)];
mergeIntervals(arr);
|
Output
The Merged Intervals are: [1, 9]
Time Complexity: O(N*log(N))
Auxiliary Space Complexity: O(1)
Share your thoughts in the comments
Please Login to comment...