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:
- Sort the given array span in non-decreasing order.
- Initialize a variable say, uniqueRanges = 1 to count unique non-coinciding spans present in the given spans array.
- Initialize a variable say, end = ranges[0][1].
- Run a loop from i = 1 to i < N and check if it is coinciding, update the variable end
- if (ranges[i][0] <= end), end = Math.max(end, ranges[i][1])
- else, increment uniqueRanges and update variable end,
- uniqueRanges++
- end = ranges[i][1]
- Return number of ways for distributing n things into two groups is (2)n,
- return power(uniqueRanges)
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)}`); |
Number of ways = 4
Time Complexity: O(N * log(N))
Auxiliary Space: O(1)