Open In App

Split the given ranges into two groups

Given a 2D array span[][] of length N which contains spans [L, R] (0 ≤ L ≤ R ≤ 109), the task is to merge those spans which are coinciding and after that split those spans into two groups.

Note: Return numbers of ways these spans can be split following the given condition. Since the answer may be very large, return it modulo 109 + 7.



Examples:

Input: span[][] = [[1, 3], [10, 20], [2, 5], [4, 8]], N = 4
Output: 4
Explanation: As span[0], span[2] and span[3] can be merged into S1: [1, 8] and S2: [10, 20] Now, there are 4 ways in which we can split S1 and S2 in two groups:



  • Case 1: group-1 contains (S1, S2) and group-2 is empty.
  • Case 2: group-1 contains (S1) and group-2 contains (S2).
  • Case 3: group-1 contains (S2) and group-2 contains (S1).
  • Case 4: group-1 is empty and group-2 contains (S1, S2).

Input: span[][] = [[6, 10], [5, 15]], N = 2
Output: 2
Explanation: As span[0] and span[1] can merged into S1: [5, 15] Now, there are 2 ways in which we can split S1 in two groups:

  • Case 1: group-1 contains (S1) and group-2 is empty.
  • Case 2: group-1 is empty and group-2 contains (S1).

Approach: To solve the problem follow the below idea:

  • Sort the given array span in non-decreasing order (on the basis of span[i][0]).
  • After sorting, iterate the array and count unique ranges which are non-coinciding.
  • We can find coinciding spans by comparing the last value of the last span and the first value of the current span, if it is smaller then, we can merge these two spans and update the last value.
  • Return number of ways for distributing n things into two groups is (2)n.

Below are the steps for the above approach:

Below is the code for the above approach:




#include <bits/stdc++.h>
using namespace std;
 
const int mod = 1e9+7;
 
int power(int num)
{
    if (num == 1)
        return 2;
    long long a = power(num / 2);
    int k = (a * a) % mod;
    if (num % 2 != 0) {
        return (k * 2LL) % mod;
    }
    return k;
}
 
int splittingWays(vector<vector<int>>& ranges)
{
    int N = ranges.size();
    // Sorting the given array
    sort(ranges.begin(), ranges.end(), [](const vector<int>& a, const vector<int>& b)
        {
            if (a[0] == b[0])
                return a[1] < b[1];
            else
                return a[0] < b[0];
        });
    // Counting unique non-overlapping
    // ranges present in the
    // given ranges array
    int uniqueRanges = 1;
    int end = ranges[0][1];
    for (int i = 1; i < N; i++) {
 
        // Checking whether it is
        // overlapping or not
        if (ranges[i][0] <= end) {
            end = max(end, ranges[i][1]);
        }
        else {
            uniqueRanges++;
            end = ranges[i][1];
        }
    }
 
    // Return 2^uniqueRanges
    return power(uniqueRanges);
}
 
int main()
{
    vector<vector<int>> ranges = { { 1, 3 }, { 10, 20 }, { 2, 5 }, { 4, 8 } };
    cout << "Number of ways = " << splittingWays(ranges) << endl;
    return 0;
}




// Java code of the above approach
 
import java.util.*;
 
class GFG {
    public static int mod = 1000000007;
    public static int power(int num)
    {
        if (num == 1)
            return 2;
        long a = power(num / 2);
        int k = (int)(a * a) % mod;
        if (num % 2 != 0) {
            return (k * 2) % mod;
        }
        return k;
    }
 
    // Drivers code
    public static void main(String[] args)
    {
        int[][] ranges
            = { { 1, 3 }, { 10, 20 }, { 2, 5 }, { 4, 8 } };
        int N = ranges.length;
        System.out.println("Number of ways = "
                           + splittingWays(ranges, N));
    }
 
    public static int splittingWays(int[][] ranges, int N)
    {
 
        // Sorting the given array
        Arrays.sort(ranges,
                    (a, b)
                        -> (a[0] == b[0]) ? a[1] - b[1]
                                          : a[0] - b[0]);
        // Counting unique non-overlapping
        // ranges present in the
        // given ranges array
        int uniqueRanges = 1;
        int end = ranges[0][1];
        for (int i = 1; i < N; i++) {
 
            // Checking whether it is
            // overlapping or not
            if (ranges[i][0] <= end) {
                end = Math.max(end, ranges[i][1]);
            }
            else {
                uniqueRanges++;
                end = ranges[i][1];
            }
        }
 
        // Return 2^uniqueRanges
        return power(uniqueRanges);
    }
}




def power(num):
    mod = 1000000007
    if num == 1:
        return 2
    a = power(num // 2)
    k = (a * a) % mod
    if num % 2 != 0:
        return (k * 2) % mod
    return k
 
def splittingWays(ranges, N):
    # Sorting the given array
    ranges.sort(key = lambda x: (x[0], x[1]))
 
    # Counting unique non-overlapping
    # ranges present in the
    # given ranges array
    uniqueRanges = 1
    end = ranges[0][1]
    for i in range(1, N):
        # Checking whether it is
        # overlapping or not
        if ranges[i][0] <= end:
            end = max(end, ranges[i][1])
        else:
            uniqueRanges += 1
            end = ranges[i][1]
 
    # Return 2^uniqueRanges
    return power(uniqueRanges)
 
ranges = [ [ 1, 3 ], [ 10, 20 ], [ 2, 5 ], [ 4, 8 ] ]
N = len(ranges)
print("Number of ways = ", splittingWays(ranges, N))
 
# Contributed by adityasha4x71




using System;
using System.Collections.Generic;
 
public class Program
{
  const int mod = 1000000007;
 
  static int Power(int num)
  {
    if (num == 1)
      return 2;
    long a = Power(num / 2);
    int k = (int)((a * a) % mod);
    if (num % 2 != 0)
    {
      return (int)((k * 2L) % mod);
    }
    return k;
  }
 
  static int SplittingWays(List<List<int>> ranges)
  {
    int N = ranges.Count;
    // Sorting the given array
    ranges.Sort((a, b) =>
                {
                  if (a[0] == b[0])
                    return a[1].CompareTo(b[1]);
                  else
                    return a[0].CompareTo(b[0]);
                });
 
    // Counting unique non-overlapping
    // ranges present in the
    // given ranges array
    int uniqueRanges = 1;
    int end = ranges[0][1];
    for (int i = 1; i < N; i++)
    {
      // Checking whether it is
      // overlapping or not
      if (ranges[i][0] <= end)
      {
        end = Math.Max(end, ranges[i][1]);
      }
      else
      {
        uniqueRanges++;
        end = ranges[i][1];
      }
    }
 
    // Return 2^uniqueRanges
    return Power(uniqueRanges);
  }
 
  public static void Main()
  {
    List<List<int>> ranges = new List<List<int>> {
      new List<int> {1, 3},
      new List<int> {10, 20},
      new List<int> {2, 5},
      new List<int> {4, 8}
    };
    Console.WriteLine($"Number of ways = {SplittingWays(ranges)}");
  }
}




const mod = 1e9 + 7;
 
function power(num) {
  if (num === 1) {
    return 2;
  }
  const a = power(Math.floor(num / 2));
  const k = (a * a) % mod;
  if (num % 2 !== 0) {
    return (k * 2n) % BigInt(mod);
  }
  return k;
}
 
function splittingWays(ranges) {
  const N = ranges.length;
  // Sorting the given array
  ranges.sort((a, b) => {
    if (a[0] === b[0]) {
      return a[1] - b[1];
    } else {
      return a[0] - b[0];
    }
  });
  // Counting unique non-overlapping
  // ranges present in the
  // given ranges array
  let uniqueRanges = 1;
  let end = ranges[0][1];
  for (let i = 1; i < N; i++) {
    // Checking whether it is
    // overlapping or not
    if (ranges[i][0] <= end) {
      end = Math.max(end, ranges[i][1]);
    } else {
      uniqueRanges++;
      end = ranges[i][1];
    }
  }
 
  // Return 2^uniqueRanges
  return power(uniqueRanges);
}
 
const ranges = [
  [1, 3],
  [10, 20],
  [2, 5],
  [4, 8]
];
console.log(`Number of ways = ${splittingWays(ranges)}`);

Output
Number of ways = 4

Time Complexity: O(N * log(N))
Auxiliary Space: O(1)


Article Tags :