Open In App

Merge Overlapping Intervals

Last Updated : 23 Jul, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given an array of time intervals where arr[i] = [starti, endi], the task is to merge all the overlapping intervals into one and output the result which should have only mutually exclusive intervals.

Given an array of time intervals where arr[i] = [starti, endi], find the merge all the overlapping intervals into one, and output the result containing only mutually exclusive intervals.

Examples:

Input: arr[] = [[1, 3], [2, 4], [6, 8], [9, 10]]
Output: [[1, 4], [6, 8], [9, 10]]
Explanation: In the given intervals, we have only two overlapping intervals [1, 3] and [2, 4]. Therefore, we will merge these two and return [[1, 4]], [6, 8], [9, 10]].

Input: arr[] = [[7, 8], [1, 5], [2, 4], [4, 6]]
Output: [[1, 6], [7, 8]]
Explanation: We will merge the overlapping intervals [[1, 5], [2, 4], [4, 6]] into a single interval [1, 6].

[Naive Approach] Checking All Possible Overlaps – O(n^2) Time and O(n) Space

A simple approach is to group all the intervals by sorting them then start from the first interval and compare it with all other intervals for overlaps. If the first interval 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.

C++
#include <bits/stdc++.h>
using namespace std;

vector<vector<int>> mergeOverlap(vector<vector<int>> &arr) {
    int n = arr.size();

    sort(arr.begin(), arr.end());
    vector<vector<int>> res;

    // Checking for all possible overlaps
    for (int i = 0; i < n; i++) {
        int start = arr[i][0];
        int end = arr[i][1];

        // Skipping already merged intervals
        if (!res.empty() && res.back()[1] >= end)
            continue;

        // Find the end of the merged range
        for (int j = i + 1; j < n; j++) {
            if (arr[j][0] <= end)
                end = max(end, arr[j][1]);
        }
        res.push_back({start, end});
    }
    return res;
}

int main() {
    vector<vector<int>> arr = {{7, 8}, {1, 5}, {2, 4}, {4, 6}};
    vector<vector<int>> res = mergeOverlap(arr);

    for (auto interval : res)
        cout << interval[0] << " " << interval[1] << endl;

    return 0;
}
Java
import java.util.ArrayList;
import java.util.Arrays;

class GfG {

    static ArrayList<int[]> mergeOverlap(int[][] arr) {
        int n = arr.length;

        Arrays.sort(arr, (a, b) -> Integer.compare(a[0], b[0]));
        ArrayList<int[]> res = new ArrayList<>();

        // Checking for all possible overlaps
        for (int i = 0; i < n; i++) {
            int start = arr[i][0];
            int end = arr[i][1];

            // Skipping already merged intervals
            if (!res.isEmpty() && res.get(res.size() - 1)[1] >= end) {
                continue;
            }

            // Find the end of the merged range
            for (int j = i + 1; j < n; j++) {
                if (arr[j][0] <= end) {
                    end = Math.max(end, arr[j][1]);
                }
            }
            res.add(new int[]{start, end});
        }
        return res;
    }

    public static void main(String[] args) {
        int[][] arr = {{7, 8}, {1, 5}, {2, 4}, {4, 6}};
        ArrayList<int[]> res = mergeOverlap(arr);

        for (int[] interval : res) {
            System.out.println(interval[0] + " " + interval[1]);
        }
    }
}
Python
def mergeOverlap(arr):
    n = len(arr)

    arr.sort()
    res = []

    # Checking for all possible overlaps
    for i in range(n):
        start = arr[i][0]
        end = arr[i][1]

        # Skipping already merged intervals
        if res and res[-1][1] >= end:
            continue

        # Find the end of the merged range
        for j in range(i + 1, n):
            if arr[j][0] <= end:
                end = max(end, arr[j][1])
        res.append([start, end])
    
    return res

if __name__ == "__main__":
    arr = [[7, 8], [1, 5], [2, 4], [4, 6]]
    res = mergeOverlap(arr)

    for interval in res:
        print(interval[0], interval[1])
C#
using System;
using System.Collections.Generic;

class GfG {
    static List<int[]> mergeOverlap(int[][] arr) {
        int n = arr.Length;

        Array.Sort(arr, (a, b) => a[0].CompareTo(b[0]));
        List<int[]> res = new List<int[]>();

        // Checking for all possible overlaps
        for (int i = 0; i < n; i++) {
            int start = arr[i][0];
            int end = arr[i][1];

            // Skipping already merged intervals
            if (res.Count > 0 && res[res.Count - 1][1] >= end)
                continue;

            // Find the end of the merged range
            for (int j = i + 1; j < n; j++) {
                if (arr[j][0] <= end)
                    end = Math.Max(end, arr[j][1]);
            }
            res.Add(new int[] { start, end });
        }
        return res;
    }
    static void Main() {
        int[][] arr = new int[][] {
            new int[] { 7, 8 },
            new int[] { 1, 5 },
            new int[] { 2, 4 },
            new int[] { 4, 6 }
        };
        List<int[]> res = mergeOverlap(arr);

        foreach (var interval in res)
            Console.WriteLine($"{interval[0]} {interval[1]}");
    }
}
JavaScript
function mergeOverlap(arr) {
    let n = arr.length;

    arr.sort((a, b) => a[0] - b[0]);
    let res = [];

    // Checking for all possible overlaps
    for (let i = 0; i < n; i++) {
        let start = arr[i][0];
        let end = arr[i][1];

        // Skipping already merged intervals
        if (res.length > 0 && res[res.length - 1][1] >= end) {
            continue;
        }

        // Find the end of the merged range
        for (let j = i + 1; j < n; j++) {
            if (arr[j][0] <= end) {
                end = Math.max(end, arr[j][1]);
            }
        }
        res.push([start, end]);
    }
    return res;
}

const arr = [[7, 8], [1, 5], [2, 4], [4, 6]];
const res = mergeOverlap(arr);

for (const interval of res) 
    console.log(interval[0], interval[1]);

Output
1 6
7 8

[Expected Approach] Checking Last Merged Interval – O(n*log(n)) Time and O(n) Space

In the previous approach, for each range we are checking for possible overlaps by iterating over all the remaining ranges till the end. We can optimize this by checking only those intervals that overlap with the last merged interval. Since the intervals will be sorted based on starting point, so if we encounter an interval whose starting time lies outside the last merged interval, then all further intervals will also lie outside it.

The intuition is to first sort the intervals based on their starting points. This allows us to easily identify overlapping intervals by comparing each interval with the last merged interval. Now, iterate over each interval and if the current interval overlaps with the last merged interval, then merge them both. Otherwise, append the merged interval to the result.

C++
#include <bits/stdc++.h>
using namespace std;

vector<vector<int>> mergeOverlap(vector<vector<int>>& arr) {

    // Sort intervals based on start values
    sort(arr.begin(), arr.end());
  
    vector<vector<int>> res;
    res.push_back(arr[0]);

    for (int i = 1; i < arr.size(); i++) {
        vector<int>& last = res.back();
        vector<int>& curr = arr[i];

        // If current interval overlaps with the last merged
        // interval, merge them 
        if (curr[0] <= last[1]) 
            last[1] = max(last[1], curr[1]);
        else 
            res.push_back(curr);
    }

    return res;
}

int main() {
    vector<vector<int>> arr = {{7, 8}, {1, 5}, {2, 4}, {4, 6}};
    vector<vector<int>> res = mergeOverlap(arr);

  	for (vector<int>& interval: res) 
        cout << interval[0] << " " << interval[1] << endl;
 
    return 0;
}
Java
import java.util.ArrayList;
import java.util.Arrays;

class GfG {

    static ArrayList<int[]> mergeOverlap(int[][] arr) {

        // Sort intervals based on start values
        Arrays.sort(arr, (a, b) -> Integer.compare(a[0], b[0]));

        ArrayList<int[]> res = new ArrayList<>();
        res.add(new int[]{arr[0][0], arr[0][1]});

        for (int i = 1; i < arr.length; i++) {
            int[] last = res.get(res.size() - 1);
            int[] curr = arr[i];

            // If current interval overlaps with the last merged interval,
            // merge them
            if (curr[0] <= last[1])
                last[1] = Math.max(last[1], curr[1]);
            else
                res.add(new int[]{curr[0], curr[1]});
        }

        return res;
    }

    public static void main(String[] args) {
        int[][] arr = {{7, 8}, {1, 5}, {2, 4}, {4, 6}};
        ArrayList<int[]> res = mergeOverlap(arr);

        for (int[] interval : res)
            System.out.println(interval[0] + " " + interval[1]);
    }
}
Python
def mergeOverlap(arr):
    
    # Sort intervals based on start values
    arr.sort()

    res = []
    res.append(arr[0])

    for i in range(1, len(arr)):
        last = res[-1]
        curr = arr[i]

        # If current interval overlaps with the last merged
        # interval, merge them 
        if curr[0] <= last[1]:
            last[1] = max(last[1], curr[1])
        else:
            res.append(curr)

    return res

if __name__ == "__main__":
    arr = [[7, 8], [1, 5], [2, 4], [4, 6]]
    res = mergeOverlap(arr)

    for interval in res:
        print(interval[0], interval[1])
C#
using System;
using System.Collections.Generic;

class GfG {

    // Merge overlapping intervals and return merged intervals as List<int[]>
    static List<int[]> mergeOverlap(List<List<int>> arr) {

        // Sort intervals based on start values
        arr.Sort((a, b) => a[0].CompareTo(b[0]));

        List<int[]> res = new List<int[]>();
        res.Add(new int[] { arr[0][0], arr[0][1] });

        for (int i = 1; i < arr.Count; i++) {
            int[] last = res[res.Count - 1];
            List<int> curr = arr[i];

            // If current interval overlaps with last, merge them
            if (last[1] >= curr[0]) {
                last[1] = Math.Max(last[1], curr[1]);
            } else {
                res.Add(new int[] { curr[0], curr[1] });
            }
        }

        return res;
    }

    static void Main() {
        List<List<int>> arr = new List<List<int>> {
            new List<int> {7, 8},
            new List<int> {1, 5},
            new List<int> {2, 4},
            new List<int> {4, 6}
        };

        // Get merged intervals
        List<int[]> merged = mergeOverlap(arr);

        // Print merged intervals
        foreach (int[] interval in merged) {
            Console.WriteLine(interval[0] + " " + interval[1]);
        }
    }
}
JavaScript
function mergeOverlap(arr) {
    if (arr.length === 0) return [];

    // Sort intervals based on start values
    const sorted = [...arr].sort((a, b) => a[0] - b[0]);

    const res = [];
    res.push(sorted[0]);

    for (let i = 1; i < sorted.length; i++) {
        const last = res[res.length - 1];
        const curr = sorted[i];

        // If current interval overlaps with last, merge them
        if (curr[0] <= last[1]) {
            last[1] = Math.max(last[1], curr[1]);
        } else {
            res.push(curr);
        }
    }

    return res;
}

// Driver Code
const arr = [[7, 8], [1, 5], [2, 4], [4, 6]];
const res = mergeOverlap(arr);

for (const interval of res) {
    console.log(interval[0] + " " + interval[1]);
}

Output
1 6
7 8

Merge Overlapping Interval
Visit Course explore course icon
Article Tags :
Practice Tags :

Similar Reads