Open In App

Merge Overlapping Intervals

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

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}} 

Recommended Practice

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;
 
// Function to merge overlapping intervals
vector<vector<int>> overlappedInterval(vector<vector<int>>& intervals) {
    if (intervals.empty()) {
        return vector<vector<int>>();
    }
 
    // Sort intervals based on start values
    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]) {
            // If current interval overlaps with the top of the stack, merge them
            top[1] = max(top[1], current[1]);
        } else {
            // If no overlap, push the current interval onto the stack
            mergedStack.push(current);
        }
    }
 
    // Convert the stack to a vector
    vector<vector<int>> mergedIntervals;
    while (!mergedStack.empty()) {
        mergedIntervals.insert(mergedIntervals.begin(), mergedStack.top());
        mergedStack.pop();
    }
 
    return mergedIntervals;
}
// Driver Code
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;
}
// This code is contributed by Veerendra_Singh_Rajpoot


Java




// A Java program for merging overlapping intervals
import java.util.Arrays;
import java.util.Comparator;
import java.util.Stack;
public class MergeOverlappingIntervals {
 
    // The main function that takes a set of intervals,
    // merges overlapping intervals and prints the result
    public static void mergeIntervals(Interval arr[])
    {
        // Test if the given set has at least one interval
        if (arr.length <= 0)
            return;
 
        // Create an empty stack of intervals
        Stack<Interval> stack = new Stack<>();
 
        // sort the intervals in increasing order of start
        // time
        Arrays.sort(arr, new Comparator<Interval>() {
            public int compare(Interval i1, Interval i2)
            {
                return i1.start - i2.start;
            }
        });
 
        // push the first interval to stack
        stack.push(arr[0]);
 
        // Start from the next interval and merge if
        // necessary
        for (int i = 1; i < arr.length; i++) {
            // get interval from stack top
            Interval top = stack.peek();
 
            // if current interval is not overlapping with
            // stack top, push it to the stack
            if (top.end < arr[i].start)
                stack.push(arr[i]);
 
            // Otherwise update the ending time of top if
            // ending of current interval is more
            else if (top.end < arr[i].end) {
                top.end = arr[i].end;
                stack.pop();
                stack.push(top);
            }
        }
 
        // Print contents of stack
        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;
    }
}
// This code is contributed by Gaurav Tiwari


Python3




# Python3 program for merging overlapping intervals
def mergeIntervals(intervals):
    # Sort the array on the basis of start values of intervals.
    intervals.sort()
    stack = []
    # insert first interval into stack
    stack.append(intervals[0])
    for i in intervals[1:]:
        # Check for overlapping interval,
        # if interval overlap
        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#




// A C# program for merging overlapping intervals
using System;
using System.Collections;
using System.Collections.Generic;
 
public class MergeOverlappingIntervals {
 
    // sort the intervals in increasing order of start time
    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;
        }
    }
 
    // The main function that takes a set of intervals,
    // merges overlapping intervals and prints the result
    public static void mergeIntervals(Interval[] arr)
    {
 
        // Test if the given set has at least one interval
        if (arr.Length <= 0)
            return;
        Array.Sort(arr, new sortHelper());
 
        // Create an empty stack of intervals
        Stack stack = new Stack();
 
        // Push the first interval to stack
        stack.Push(arr[0]);
 
        // Start from the next interval and merge if
        // necessary
        for (int i = 1; i < arr.Length; i++) {
 
            // get interval from stack top
            Interval top = (Interval)stack.Peek();
 
            // if current interval is not overlapping with
            // stack top, Push it to the stack
            if (top.end < arr[i].start)
                stack.Push(arr[i]);
 
            // Otherwise update the ending time of top if
            // ending of current interval is more
            else if (top.end < arr[i].end) {
                top.end = arr[i].end;
                stack.Pop();
                stack.Push(top);
            }
        }
 
        // Print contents of stack
        Console.Write("The Merged Intervals are: ");
        while (stack.Count != 0) {
            Interval t = (Interval)stack.Pop();
            Console.Write("[" + t.start + "," + t.end
                          + "] ");
        }
    }
 
    // Driver code
    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;
    }
}
 
// This code is contributed by rutvik_56.


Javascript




// A JavaScript program for merging overlapping intervals
 
// An interval has start time and end time
class Interval {
    constructor(start, end) {
        this.start = start;
        this.end = end;
    }
}
 
// Compares two intervals according to their starting time.
function compareInterval(i1, i2) {
    return (i1.start < i2.start);
}
 
// The main function that takes a set of intervals, merges
// overlapping intervals and prints the result
function mergeIntervals(arr) {
    // Test if the given set has at least one interval
    if (arr.length <= 0)
        return;
 
    // Create an empty stack of intervals
    let s = [];
 
    // sort the intervals in increasing order of start time
    arr.sort(compareInterval);
 
    // push the first interval to stack
    s.push(arr[0]);
 
    // Start from the next interval and merge if necessary
    for (let i = 1; i < arr.length; i++) {
        // get interval from stack top
        let top = s[s.length-1];
 
        // if current interval is not overlapping with stack
        // top, push it to the stack
        if (top.end < arr[i].start)
            s.push(arr[i]);
 
        // Otherwise update the ending time of top if ending
        // of current interval is more
        else if (top.end < arr[i].end) {
            top.end = arr[i].end;
            s.pop();
            s.push(top);
        }
    }
 
    // Print contents of stack
    console.log("The Merged Intervals are: ");
    while (s.length > 0) {
        let t = s.pop();
        console.log("[" + t.start + "," + t.end + "] ");
    }
    return;
}
 
// Driver program
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




// C++ program to merge overlapping Intervals in
// O(n Log n) time and O(1) extra space.
#include <bits/stdc++.h>
using namespace std;
 
// An Interval
struct Interval {
    int s, e;
};
 
// Function used in sort
bool mycomp(Interval a, Interval b) { return a.s < b.s; }
 
void mergeIntervals(Interval arr[], int n)
{
    // Sort Intervals in increasing order of
    // start time
    sort(arr, arr + n, mycomp);
 
    int index = 0; // Stores index of last element
    // in output array (modified arr[])
 
    // Traverse all input Intervals
    for (int i = 1; i < n; i++) {
        // If this is not first Interval and overlaps
        // with the previous one
        if (arr[index].e >= arr[i].s) {
            // Merge previous and current Intervals
            arr[index].e = max(arr[index].e, arr[i].e);
        }
        else {
            index++;
            arr[index] = arr[i];
        }
    }
 
    // Now arr[0..index-1] stores the merged Intervals
    cout << "\n The Merged Intervals are: ";
    for (int i = 0; i <= index; i++)
        cout << "[" << arr[i].s << ", " << arr[i].e << "] ";
}
 
// Driver program
int main()
{
    Interval arr[]
        = { { 6, 8 }, { 1, 9 }, { 2, 4 }, { 4, 7 } };
    int n = sizeof(arr) / sizeof(arr[0]);
    mergeIntervals(arr, n);
    return 0;
}
 
// This code is contributed by Aditya Kumar (adityakumar129)


C




// C program to merge overlapping Intervals in
// O(n Log n) time and O(1) extra space.
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
 
// An Interval
typedef struct Interval {
    int s, e;
} Interval;
 
// Function used in sort
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);
}
 
// Find maximum between two numbers.
int max(int num1, int num2)
{
    return (num1 > num2) ? num1 : num2;
}
 
void mergeIntervals(Interval arr[], int n)
{
    // Sort Intervals in increasing order of
    // start time
    qsort(arr, n, sizeof(Interval), mycomp);
 
    int index = 0; // Stores index of last element
    // in output array (modified arr[])
 
    // Traverse all input Intervals
    for (int i = 1; i < n; i++) {
        // If this is not first Interval and overlaps
        // with the previous one
        if (arr[index].e >= arr[i].s) {
            // Merge previous and current Intervals
            arr[index].e = max(arr[index].e, arr[i].e);
        }
        else {
            index++;
            arr[index] = arr[i];
        }
    }
 
    // Now arr[0..index-1] stores the merged Intervals
    printf("\n The Merged Intervals are: ");
    for (int i = 0; i <= index; i++)
        printf("[%d, %d]", arr[i].s, arr[i].e);
}
 
// Driver program
int main()
{
    Interval arr[]
        = { { 6, 8 }, { 1, 9 }, { 2, 4 }, { 4, 7 } };
    int n = sizeof(arr) / sizeof(arr[0]);
    mergeIntervals(arr, n);
    return 0;
}
 
// This code is contributed by Aditya Kumar (adityakumar129)


Java




// Java program to merge overlapping Intervals in
// O(n Log n) time and O(1) extra space
 
import java.util.Arrays;
import java.util.Comparator;
 
// An Interval
class Interval {
    int start, end;
 
    Interval(int start, int end)
    {
        this.start = start;
        this.end = end;
    }
}
 
public class MergeOverlappingIntervals {
 
    // Function that takes a set of intervals, merges
    // overlapping intervals and prints the result
    public static void mergeIntervals(Interval arr[])
    {
        // Sort Intervals in increasing order of
        // start time
        Arrays.sort(arr, new Comparator<Interval>() {
            public int compare(Interval i1, Interval i2)
            {
                return i1.start - i2.start;
            }
        });
 
        int index = 0; // Stores index of last element
        // in output array (modified arr[])
 
        // Traverse all input Intervals
        for (int i = 1; i < arr.length; i++) {
            // If this is not first Interval and overlaps
            // with the previous one
            if (arr[index].end >= arr[i].start) {
                // Merge previous and current Intervals
                arr[index].end
                    = Math.max(arr[index].end, arr[i].end);
            }
            else {
                index++;
                arr[index] = arr[i];
            }
        }
 
        // Now arr[0..index-1] stores the merged Intervals
        System.out.print("The Merged Intervals are: ");
        for (int i = 0; i <= index; i++) {
            System.out.print("[" + arr[i].start + ","
                             + arr[i].end + "]");
        }
    }
 
    // Driver Code
    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);
    }
}
 
// This code is contributed by Gaurav Tiwari
// This code was fixed by Subham Mukhopadhyay


Python3




# Python program to merge overlapping Intervals in
# O(n Log n) time and O(1) extra space
 
 
def mergeIntervals(arr):
 
    # Sorting based on the increasing order
    # of the start intervals
    arr.sort(key=lambda x: x[0])
 
    # Stores index of last element
    # in output array (modified arr[])
    index = 0
 
    # Traverse all input Intervals starting from
    # second interval
    for i in range(1, len(arr)):
 
        # If this is not first Interval and overlaps
        # with the previous one, Merge previous and
        # current Intervals
        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=" ")
 
 
# Driver code
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 {
 
    // Function that takes a set of intervals, merges
    // overlapping intervals and prints the result
    public static void MergeIntervals(Interval[] arr)
    {
        // Sort Intervals in increasing order of
        // start time
        arr = arr.OrderBy(x = > x.start).ToArray();
 
        int index = 0; // Stores index of last element
        // in output array (modified arr[])
 
        // Traverse all input Intervals
        for (int i = 1; i < arr.Length; i++) {
            // If this is not first Interval and overlaps
            // with the previous one
            if (arr[index].end >= arr[i].start) {
                // Merge previous and current Intervals
                arr[index].end
                    = Math.Max(arr[index].end, arr[i].end);
            }
            else {
                index++;
                arr[index] = arr[i];
            }
        }
 
        // Now arr[0..index-1] stores the merged Intervals
        Console.WriteLine("The Merged Intervals are: ");
        for (int i = 0; i <= index; i++) {
            Console.WriteLine("[" + arr[i].start + ","
                              + arr[i].end + "]");
        }
    }
 
    // Driver Code
    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




// A JavaScript program for merging overlapping intervals
 
// An interval has start time and end time
class Interval {
    constructor(s, e) {
        this.s = s;
        this.e = e;
    }
}
 
// Function used in sort
function mycomp(a, b) {
    return a.s < b.s;
}
 
// The main function that takes a set of intervals, merges
// overlapping intervals and prints the result
function mergeIntervals(arr) {
    // Sort Intervals in increasing order of
    // start time
    arr.sort(mycomp);
 
    let index = 0; // Stores index of last element
    // in output array (modified arr[])
 
    // Traverse all input Intervals
    for (let i = 1; i < arr.length; i++) {
        // If this is not first Interval and overlaps
        // with the previous one
        if (arr[index].e >= arr[i].s) {
            // Merge previous and current Intervals
            arr[index].e = Math.max(arr[index].e, arr[i].e);
        }
        else {
            index++;
            arr[index] = arr[i];
        }
    }
 
    // Now arr[0..index-1] stores the merged Intervals
    console.log("\n The Merged Intervals are: ");
    for (let i = 0; i <= index; i++)
        console.log("[" + arr[i].s + ", " + arr[i].e + "] ");
}
 
// Driver program
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)



Last Updated : 19 Oct, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads