Maximal Disjoint Intervals

Last Updated : 11 Jul, 2025

Given a 2D array arr[][] of order nx2, representing n intervals with start and end points, the task is to find the maximal set of mutually disjoint intervals

Note: Two intervals [i, j] & [k, l] are said to be disjoint if they do not have any point in common. 

Examples:  

Input: arr[][] = [[1, 4], [2, 3], [4, 6], [8, 9]]
Output: 
2 3 
4 6 
8 9 
Explanation: if [1, 4] is included then we cannot include [2, 3] & [4, 6].

Input: arr[][] = [[1, 9], [2, 3], [5, 7]]
Output: 
2 3
5 7

Try It Yourself
redirect icon

This problem is mainly a variation of Activity Selection Problem.

[Naive Approach] Generate All Subsets - O(n^2 * 2^n) Time and O(n) Space

  1. Generate all subsets of the given set of intervals.
  2. Check if a subset contains only mutually disjoint intervals by comparing start and end times.
  3. Keep track of the largest valid subset.
C++
#include <iostream>
#include <vector>
using namespace std;

// Function to check if a subs 
// of intervals is mutually disjoint
bool isDisj(vector<vector<int>> &subs) {
    int n = subs.size();
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            
            // If there is any overlapping
            if (subs[i][1] > subs[j][0] &&
                subs[i][0] < subs[j][1])
                return false; 
        }
    }
    return true;
}

// Function to find the maximal set of mutually
// disjoint intervals
vector<vector<int>> maxDisj(vector<vector<int>> &arr) {
    int n = arr.size();
    vector<vector<int>> res;

    // Generate all subsets using bitmasking
    int subCnt = (1 << n);
    for (int mask = 0; mask < subCnt; mask++) {
        vector<vector<int>> subs;

        // Form subs based on mask bits
        for (int i = 0; i < n; i++) {
            if (mask & (1 << i)) {
                subs.push_back(arr[i]);
            }
        }

        // Check if the subs is disjoint
        if (isDisj(subs) && subs.size() > res.size()) {
            res = subs; 
        }
    }

    return res;
}

// Driver code
int main() {
    vector<vector<int>> arr = {{1, 4}, {2, 3}, {4, 6}, {8, 9}};
    vector<vector<int>> result = maxDisj(arr);

    for (auto &interval : result) {
        cout << interval[0] << " " << interval[1] << endl;
    }

    return 0;
}
Java
// Function to check if a subset of intervals 
// is mutually disjoint
public static boolean isDisj(int[][] subs) {
    int n = subs.length;
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            
            // If there is any overlapping
            if (subs[i][1] > subs[j][0] && 
                subs[i][0] < subs[j][1]) {
                return false;
            }
        }
    }
    return true;
}

// Function to find the maximal set of mutually
// disjoint intervals
public static int[][] maxDisj(int[][] arr) {
    int n = arr.length;
    List<int[]> res = new ArrayList<>();

    // Generate all subsets using bitmasking
    int subCnt = 1 << n;
    for (int mask = 0; mask < subCnt; mask++) {
        List<int[]> subs = new ArrayList<>();

        // Form subs based on mask bits
        for (int i = 0; i < n; i++) {
            if ((mask & (1 << i)) != 0) {
                subs.add(arr[i]);
            }
        }

        // Check if the subs is disjoint
        if (isDisj(subs.toArray(new int[subs.size()][])) && subs.size() > res.size()) {
            res = subs;
        }
    }

    return res.toArray(new int[res.size()][]);
}

// Driver code
int[][] arr = new int[][] { { 1, 4 }, { 2, 3 }, { 4, 6 }, { 8, 9 } };
int[][] result = maxDisj(arr);

for (int[] interval : result) {
    System.out.println(interval[0] + " " + interval[1]);
}
Python
# Function to check if a subs 
# of intervals is mutually disjoint
def is_disj(subs):
    n = len(subs)
    for i in range(n):
        for j in range(i + 1, n):
            # If there is any overlapping
            if subs[i][1] > subs[j][0] and subs[i][0] < subs[j][1]:
                return False
    return True

# Function to find the maximal set of mutually
# disjoint intervals
def max_disj(arr):
    n = len(arr)
    res = []

    # Generate all subsets using bitmasking
    sub_cnt = 1 << n
    for mask in range(sub_cnt):
        subs = []

        # Form subs based on mask bits
        for i in range(n):
            if mask & (1 << i):
                subs.append(arr[i])

        # Check if the subs is disjoint
        if is_disj(subs) and len(subs) > len(res):
            res = subs

    return res

# Driver code
arr = [[1, 4], [2, 3], [4, 6], [8, 9]]
result = max_disj(arr)

for interval in result:
    print(interval[0], interval[1])
C#
// Function to check if a subset of intervals is mutually disjoint
public static bool IsDisj(int[,] subs)
{
    int n = subs.GetLength(0);
    for (int i = 0; i < n; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            // If there is any overlapping
            if (subs[i, 1] > subs[j, 0] && subs[i, 0] < subs[j, 1])
            {
                return false;
            }
        }
    }
    return true;
}

// Function to find the maximal set of
// mutually disjoint intervals
public static List<int[]> MaxDisj(int[,] arr)
{
    int n = arr.GetLength(0);
    List<int[]> res = new List<int[]>();

    // Generate all subsets using bitmasking
    int subCnt = 1 << n;
    for (int mask = 0; mask < subCnt; mask++)
    {
        List<int[]> subs = new List<int[]>();

        // Form subs based on mask bits
        for (int i = 0; i < n; i++)
        {
            if ((mask & (1 << i)) != 0)
            {
                subs.Add(new int[] { arr[i, 0], arr[i, 1] });
            }
        }

        // Check if the subs is disjoint
        if (IsDisj(arr) && subs.Count > res.Count)
        {
            res = subs;
        }
    }

    return res;
}

// Driver code
int[,] arr = new int[,] { { 1, 4 }, { 2, 3 }, { 4, 6 }, { 8, 9 } };
List<int[]> result = MaxDisj(arr);

foreach (var interval in result)
{
    Console.WriteLine(interval[0] + " " + interval[1]);
}
JavaScript
// Function to check if a subs 
// of intervals is mutually disjoint
function isDisj(subs) {
    let n = subs.length;
    for (let i = 0; i < n; i++) {
        for (let j = i + 1; j < n; j++) {
            // If there is any overlapping
            if (subs[i][1] > subs[j][0] && subs[i][0] < subs[j][1])
                return false;
        }
    }
    return true;
}

// Function to find the maximal set of mutually
// disjoint intervals
function maxDisj(arr) {
    let n = arr.length;
    let res = [];

    // Generate all subsets using bitmasking
    let subCnt = 1 << n;
    for (let mask = 0; mask < subCnt; mask++) {
        let subs = [];

        // Form subs based on mask bits
        for (let i = 0; i < n; i++) {
            if (mask & (1 << i)) {
                subs.push(arr[i]);
            }
        }

        // Check if the subs is disjoint
        if (isDisj(subs) && subs.length > res.length) {
            res = subs;
        }
    }

    return res;
}

// Driver code
let arr = [[1, 4], [2, 3], [4, 6], [8, 9]];
let result = maxDisj(arr);

for (let interval of result) {
    console.log(interval[0], interval[1]);
}

Output
2 3
4 6
8 9

[Expected Approach] Using Greedy Approach - O(n*log(n)) Time and O(1) Space.

The idea is to include the intervals with smallest end points as it will allow to include most of the other intervals. To do so, first sort the given array arr[][] based on their end points. Create a 2d array res[][] to store set of intervals and a counter end, initialized with -1, it will store the end point of last included interval. For each index i, check if start point of arr[i] i.e. arr[i][0] is greater than end, if so, add current element in res[] and update end to end point of arr[i] i.e. arr[i][1], else skip the element.

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


bool comp(const vector<int> &a, const vector<int> &b)
{
    return (a[1] < b[1]);
}

// Function to find maximal disjoint set
vector<vector<int>> getDisjoint(vector<vector<int>> &arr)
{

    // Sort the array of intervals
    // based on second element
    sort(arr.begin(), arr.end(), comp);

    // Stores the end point of the last
    // interval included in the maximal
    int end = -1;

    // Stores the maximal disjoint set
    vector<vector<int>> ans;

    for (int i = 0; i < arr.size(); i++)
    {

        if (arr[i][0] > end)
        {
            ans.push_back(arr[i]);
            end = arr[i][1];
        }
    }

    return ans;
}

// Driver code
int main()
{
    vector<vector<int>> arr = {{1, 4}, {2, 3}, {4, 6}, {8, 9}};
    vector<vector<int>> ans = getDisjoint(arr);
    for (int i = 0; i < ans.size(); i++)
    {
        cout << ans[i][0] << " " << ans[i][1] << endl;
    }
    return 0;
}
Java
import java.util.Arrays;

class GfG {

    // Function to find maximal disjoint set without using a
    // list
    static int[][] getDisjoint(int[][] arr)
    {
        // Sort the intervals based on end time
        Arrays.sort(arr,
                    (a, b) -> Integer.compare(a[1], b[1]));

        // Count the maximum number of disjoint intervals
        int count = 0;
        int end = -1;

        // First, determine the size of the result array
        for (int i = 0; i < arr.length; i++) {
            if (arr[i][0] > end) {
                count++;
                end = arr[i][1];
            }
        }

        // Create an array of appropriate size
        int[][] result = new int[count][2];
        end = -1;
        int index = 0;

        // Fill the result array with disjoint intervals
        for (int i = 0; i < arr.length; i++) {
            if (arr[i][0] > end) {
                result[index][0] = arr[i][0];
                result[index][1] = arr[i][1];
                index++;
                end = arr[i][1];
            }
        }

        return result;
    }

    // Driver code
    public static void main(String[] args)
    {
        int[][] arr
            = { { 1, 4 }, { 2, 3 }, { 4, 6 }, { 8, 9 } };

        // Call getDisjoint function
        int[][] ans = getDisjoint(arr);

        // Print the maximal disjoint intervals
        for (int i = 0; i < ans.length; i++) {
            System.out.println(ans[i][0] + " " + ans[i][1]);
        }
    }
}
Python
def getDisjoint(arr):

    # Sort the array of intervals
    # based on second element
    arr.sort(key=lambda x: x[1])

    # Stores the end point of the last
    # interval included in the maximal
    end = -1

    # Stores the maximal disjoint set
    ans = []

    for i in range(len(arr)):

        # If the current interval has
        # start point greater than the
        # end point of the last interval
        if arr[i][0] > end:
            ans.append(arr[i])
            end = arr[i][1]

    return ans


# Driver code
if __name__ == "__main__":
    arr = [
        [1, 4],
        [2, 3],
        [4, 6],
        [8, 9]
    ]
    ans = getDisjoint(arr)
    for interval in ans:
        print(interval[0], interval[1])
C#
using System;

class GfG
{
    // Function to find maximal disjoint set without using a List
    static int[,] getDisjoint(int[,] arr)
    {
        int n = arr.GetLength(0);

        // Convert 2D array to 1D array of intervals for sorting
        int[][] intervals = new int[n][];
        for (int i = 0; i < n; i++)
            intervals[i] = new int[] { arr[i, 0], arr[i, 1] };

        // Sort intervals based on end time
        Array.Sort(intervals, (a, b) => a[1].CompareTo(b[1]));

        // Count the number of disjoint intervals
        int count = 0, end = -1;

        for (int i = 0; i < n; i++)
        {
            if (intervals[i][0] > end)
            {
                count++;
                end = intervals[i][1];
            }
        }

        // Create a fixed-size array to store the result
        int[,] result = new int[count, 2];
        end = -1;
        int index = 0;

        // Fill the result array with disjoint intervals
        for (int i = 0; i < n; i++)
        {
            if (intervals[i][0] > end)
            {
                result[index, 0] = intervals[i][0];
                result[index, 1] = intervals[i][1];
                index++;
                end = intervals[i][1];
            }
        }

        return result;
    }

    // Driver code
    static void Main(string[] args)
    {
        int[,] arr = { { 1, 4 }, { 2, 3 }, { 4, 6 }, { 8, 9 } };

        // Call getDisjoint function
        int[,] ans = getDisjoint(arr);

        // Print the maximal disjoint intervals
        for (int i = 0; i < ans.GetLength(0); i++)
        {
            Console.WriteLine(ans[i, 0] + " " + ans[i, 1]);
        }
    }
}
JavaScript
function getDisjoint(arr)
{

    // Sort the array of intervals
    // based on second element
    arr.sort((a, b) => a[1] - b[1]);

    // Stores the end point of the last
    // interval included in the maximal
    let end = -1;

    // Stores the maximal disjoint set
    let ans = [];

    for (let i = 0; i < arr.length; i++) {

        if (arr[i][0] > end) {
            ans.push(arr[i]);
            end = arr[i][1];
        }
    }

    return ans;
}

let arr = [ [ 1, 4 ], [ 2, 3 ], [ 4, 6 ], [ 8, 9 ] ];
let ans = getDisjoint(arr);
ans.forEach(
    interval => { console.log(interval[0], interval[1]); });

Output
2 3
4 6
8 9


Comment