Overlapping Intervals

Last Updated : 16 Jul, 2026

Given an array of time intervals where arr[i] = [starti, endi], our task is to merge all the overlapping intervals into one and output the result which should have 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].

Try It Yourself
redirect icon

[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<ArrayList<Integer>> mergeOverlap(int[][] arr) {
        int n = arr.length;

        Arrays.sort(arr, (a, b) -> Integer.compare(a[0], b[0]));
        ArrayList<ArrayList<Integer>> 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).get(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]);
                }
            }

            ArrayList<Integer> interval = new ArrayList<>();
            interval.add(start);
            interval.add(end);
            res.add(interval);
        }
        return res;
    }

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

        for (ArrayList<Integer> interval : res) {
            System.out.println(interval.get(0) + " " + interval.get(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<List<int>> mergeOverlap(int[][] arr) {
        int n = arr.Length;

        Array.Sort(arr, (a, b) => a[0].CompareTo(b[0]));
        List<List<int>> res = new List<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 List<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<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.

  • Sort the intervals based on their starting points so that overlapping intervals appear consecutively.
  • Iterate through the sorted intervals while maintaining the last merged interval.
  • If the current interval overlaps with the last merged interval, merge them by updating the ending point.
  • Otherwise, append the last merged interval to the result and start a new merged interval with the current interval.
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<ArrayList<Integer>> mergeOverlap(int[][] arr) {

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

        ArrayList<ArrayList<Integer>> res = new ArrayList<>();

        ArrayList<Integer> first = new ArrayList<>();
        first.add(arr[0][0]);
        first.add(arr[0][1]);
        res.add(first);

        for (int i = 1; i < arr.length; i++) {
            ArrayList<Integer> 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.get(1))
                last.set(1, Math.max(last.get(1), curr[1]));
            else {
                ArrayList<Integer> interval = new ArrayList<>();
                interval.add(curr[0]);
                interval.add(curr[1]);
                res.add(interval);
            }
        }

        return res;
    }

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

        for (ArrayList<Integer> interval : res)
            System.out.println(interval.get(0) + " " + interval.get(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 {

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

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

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

        for (int i = 1; i < arr.Length; i++) {
            List<int> last = res[res.Count - 1];
            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 List<int> { curr[0], curr[1] });
            }
        }

        return res;
    }

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

        List<List<int>> merged = mergeOverlap(arr);

        foreach (List<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
Comment