Count number of subsets whose median is also present in the same subset
Given an array arr[] of size N, the task is to count the number of ways we can select a subset from the given array elements such that the median of the selected subset is also present as an element in the subset. Since this number may be large, compute it modulo 1000000007.
Examples:
Input: arr[] = {2, 3, 2}
Output: 5
{2}, {3}, {2}, {2, 2} and {2, 3, 2} are all possible valid sub-sets.
Input: arr[] = {1, 4, 2, 2, 3, 5}
Output: 36
Approach:
- Every subset of odd size has its median present in the subset, so, we can directly add 2N – 1 to the answer.
- For an even size subset, The subset will be selected, if and only if the middle two elements are equal.
- We need to count the number of even-sized subsets with equal middle elements.
The Simple solution would be to iterate over every pair of equal elements (i, j) such that A[i] = A[j] and iterate over the size 2 * X of a subset from X = 1 to N. The number of ways to make the subset of size X with two fixed middle elements is just the product of the number of ways we can select X – 1 element from [1, i – 1] and X – 1 element from [j + 1, N].
This solution requires to iterate over every pair (i, j) which takes O(N2) time and O(N) time per pair, leading to Overall time complexity O(N3)
Below is the implementation of the above approach:
C++
#include <algorithm>
#include <iostream>
using namespace std;
long long mod = 1000000007;
int fact( int n)
{
int res = 1;
for ( int i = 2; i <= n; i++)
res = res * i;
return res;
}
int nCr( int n, int r)
{
return fact(n) / (fact(r) * fact(n - r));
}
long long powmod( long long a, long long n)
{
if (!n)
return 1;
long long pt = powmod(a, n / 2);
pt = (pt * pt) % mod;
if (n % 2)
return (pt * a) % mod;
else
return pt;
}
long long CountSubset( int * arr, int n)
{
long long ans = powmod(2, n - 1);
sort(arr, arr + n);
for ( int i = 0; i < n; ++i) {
int j = i + 1;
while (j < n && arr[j] == arr[i]) {
int r = n - 1 - j;
int l = i;
ans = (ans + nCr(l + r, l)) % mod;
j++;
}
}
return ans;
}
int main()
{
int arr[] = { 2, 3, 2 };
int n = sizeof (arr) / sizeof (arr[0]);
cout << CountSubset(arr, n) << endl;
return 0;
}
|
Java
import java.util.*;
class GFG {
static long mod = 1000000007 ;
static int fact( int n)
{
int res = 1 ;
for ( int i = 2 ; i <= n; i++)
res = res * i;
return res;
}
static int nCr( int n, int r)
{
return fact(n) / (fact(r) * fact(n - r));
}
static long powmod( long a, long n)
{
if (n == 0 )
return 1 ;
long pt = powmod(a, n / 2 );
pt = (pt * pt) % mod;
if (n % 2 == 1 )
return (pt * a) % mod;
else
return pt;
}
static long CountSubset( int [] arr, int n)
{
long ans = powmod( 2 , n - 1 );
Arrays.sort(arr);
for ( int i = 0 ; i < n; ++i) {
int j = i + 1 ;
while (j < n && arr[j] == arr[i]) {
int r = n - 1 - j;
int l = i;
ans = (ans + nCr(l + r, l)) % mod;
j++;
}
}
return ans;
}
public static void main(String[] args)
{
int arr[] = { 2 , 3 , 2 };
int n = arr.length;
System.out.println(CountSubset(arr, n));
}
}
|
Python3
mod = 1000000007
def fact(n):
res = 1
for i in range ( 2 , n + 1 ):
res = res * i
return res
def nCr(n, r):
return int (fact(n) / (fact(r) *
fact(n - r)))
def powmod(a, n):
if (n = = 0 ):
return 1
pt = powmod(a, int (n / 2 ))
pt = (pt * pt) % mod
if (n % 2 ):
return (pt * a) % mod
else :
return pt
def CountSubset(arr, n):
ans = powmod( 2 , n - 1 )
arr.sort(reverse = False )
for i in range (n):
j = i + 1
while (j < n and arr[j] = = arr[i]):
r = n - 1 - j
l = i
ans = (ans + nCr(l + r, l)) % mod
j + = 1
return ans
if __name__ = = '__main__' :
arr = [ 2 , 3 , 2 ]
n = len (arr)
print (CountSubset(arr, n))
|
C#
using System;
class GFG {
static long mod = 1000000007;
static int fact( int n)
{
int res = 1;
for ( int i = 2; i <= n; i++)
res = res * i;
return res;
}
static int nCr( int n, int r)
{
return fact(n) / (fact(r) * fact(n - r));
}
static long powmod( long a, long n)
{
if (n == 0)
return 1;
long pt = powmod(a, n / 2);
pt = (pt * pt) % mod;
if (n % 2 == 1)
return (pt * a) % mod;
else
return pt;
}
static long CountSubset( int [] arr, int n)
{
long ans = powmod(2, n - 1);
Array.Sort(arr);
for ( int i = 0; i < n; ++i) {
int j = i + 1;
while (j < n && arr[j] == arr[i]) {
int r = n - 1 - j;
int l = i;
ans = (ans + nCr(l + r, l)) % mod;
j++;
}
}
return ans;
}
public static void Main(String[] args)
{
int [] arr = { 2, 3, 2 };
int n = arr.Length;
Console.WriteLine(CountSubset(arr, n));
}
}
|
PHP
<?php
$mod = 1000000007;
function fact( $n )
{
$res = 1;
for ( $i = 2; $i <= $n ; $i ++)
$res = $res * $i ;
return $res ;
}
function nCr( $n , $r )
{
return fact( $n ) / (fact( $r ) * fact( $n - $r ));
}
function powmod( $a , $n )
{
global $mod ;
if ( $n == 0)
return 1;
$pt = powmod( $a , $n / 2);
$pt = ( $pt * $pt ) % $mod ;
if ( $n % 2 == 1)
return ( $pt * $a ) % $mod ;
else
return $pt ;
}
function CountSubset( $arr , $n )
{
global $mod ;
$ans = powmod(2, $n - 1);
sort( $arr , 0);
for ( $i = 0; $i < $n ; ++ $i )
{
$j = $i + 1;
while ( $j < $n && $arr [ $j ] == $arr [ $i ])
{
$r = $n - 1 - $j ;
$l = $i ;
$ans = ( $ans + nCr( $l + $r , $l )) % $mod ;
$j ++;
}
}
return $ans ;
}
{
$arr = array (2, 3, 2 );
$n = sizeof( $arr );
echo (CountSubset( $arr , $n ));
}
|
Javascript
<script>
const mod = 1000000007;
function fact(n)
{
let res = 1;
for (let i = 2; i <= n; i++)
res = res * i;
return res;
}
function nCr(n, r)
{
return parseInt(fact(n) / (fact(r) * fact(n - r)));
}
function powmod(a, n)
{
if (!n)
return 1;
let pt = powmod(a, parseInt(n / 2));
pt = (pt * pt) % mod;
if (n % 2)
return (pt * a) % mod;
else
return pt;
}
function CountSubset(arr, n)
{
let ans = powmod(2, n - 1);
arr.sort();
for (let i = 0; i < n; ++i) {
let j = i + 1;
while (j < n && arr[j] == arr[i]) {
let r = n - 1 - j;
let l = i;
ans = (ans + nCr(l + r, l)) % mod;
j++;
}
}
return ans;
}
let arr = [ 2, 3, 2 ];
let n = arr.length;
document.write(CountSubset(arr, n));
</script>
|
Time Complexity: O(N3), as we are using nested loops for traversing N*N times and in each traversal we are calling the function NCR which costs O(N). Where N is the number of elements in the array.
Auxiliary Space: O(1), as we are not using any extra space.
The time complexity of the above approach can be reduced to O(N2) if we store pascal triangle in 2-d array. So, now we don’t have to calculate factorial again and again. Read more about Pascal triangle here.
Below is the implementation of the above approach:
C++
#include <algorithm>
#include <iostream>
using namespace std;
long long mod = 1000000007;
long long arr[1001][1001];
void Preprocess()
{
arr[0][0] = 1;
for ( int i = 1; i <= 1000; ++i) {
arr[i][0] = 1;
for ( int j = 1; j < i; ++j) {
arr[i][j] = (arr[i - 1][j - 1] + arr[i - 1][j]) % mod;
}
arr[i][i] = 1;
}
}
long long powmod( long long a, long long n)
{
if (!n)
return 1;
long long pt = powmod(a, n / 2);
pt = (pt * pt) % mod;
if (n % 2)
return (pt * a) % mod;
else
return pt;
}
long long CountSubset( int * val, int n)
{
long long ans = powmod(2, n - 1);
sort(val, val + n);
for ( int i = 0; i < n; ++i) {
int j = i + 1;
while (j < n && val[j] == val[i]) {
int r = n - 1 - j;
int l = i;
ans = (ans + arr[l + r][l]) % mod;
j++;
}
}
return ans;
}
int main()
{
Preprocess();
int val[] = { 2, 3, 2 };
int n = sizeof (val) / sizeof (val[0]);
cout << CountSubset(val, n) << endl;
return 0;
}
|
Java
import java.util.Arrays;
class GFG
{
static long mod = 1000000007 ;
static long [][] arr = new long [ 1001 ][ 1001 ];
static void Preprocess()
{
arr[ 0 ][ 0 ] = 1 ;
for ( int i = 1 ; i <= 1000 ; ++i)
{
arr[i][ 0 ] = 1 ;
for ( int j = 1 ; j < i; ++j)
{
arr[i][j] = (arr[i - 1 ][j - 1 ] + arr[i - 1 ][j]) % mod;
}
arr[i][i] = 1 ;
}
}
static long powmod( long a, long n)
{
if (n == 0 )
{
return 1 ;
}
long pt = powmod(a, n / 2 );
pt = (pt * pt) % mod;
if (n % 2 == 1 )
{
return (pt * a) % mod;
}
else
{
return pt;
}
}
static long CountSubset( int [] val, int n)
{
long ans = powmod( 2 , n - 1 );
Arrays.sort(val);
for ( int i = 0 ; i < n; ++i)
{
int j = i + 1 ;
while (j < n && val[j] == val[i])
{
int r = n - 1 - j;
int l = i;
ans = (ans + arr[l + r][l]) % mod;
j++;
}
}
return ans;
}
public static void main(String[] args)
{
Preprocess();
int val[] = { 2 , 3 , 2 };
int n = val.length;
System.out.println(CountSubset(val, n));
}
}
|
Python3
mod = 1000000007
arr = [[ None for i in range ( 1001 )] for j in range ( 1001 )]
def Preprocess():
arr[ 0 ][ 0 ] = 1
for i in range ( 1 , 1001 ):
arr[i][ 0 ] = 1
for j in range ( 1 , i):
arr[i][j] = (arr[i - 1 ][j - 1 ] + arr[i - 1 ][j]) % mod
arr[i][i] = 1
def powmod(a, n):
if not n:
return 1
pt = powmod(a, n / / 2 )
pt = (pt * pt) % mod
if n % 2 :
return (pt * a) % mod
else :
return pt
def CountSubset(val, n):
ans = powmod( 2 , n - 1 )
val.sort()
for i in range ( 0 , n):
j = i + 1
while j < n and val[j] = = val[i]:
r = n - 1 - j
l = i
ans = (ans + arr[l + r][l]) % mod
j + = 1
return ans
if __name__ = = "__main__" :
Preprocess()
val = [ 2 , 3 , 2 ]
n = len (val)
print (CountSubset(val, n))
|
C#
using System;
class GFG
{
static long mod = 1000000007;
static long [,]arr = new long [1001,1001];
static void Preprocess()
{
arr[0,0] = 1;
for ( int i = 1; i <= 1000; ++i)
{
arr[i,0] = 1;
for ( int j = 1; j < i; ++j)
{
arr[i,j] = (arr[i - 1,j - 1] + arr[i - 1,j]) % mod;
}
arr[i,i] = 1;
}
}
static long powmod( long a, long n)
{
if (n == 0)
{
return 1;
}
long pt = powmod(a, n / 2);
pt = (pt * pt) % mod;
if (n % 2 == 1)
{
return (pt * a) % mod;
}
else
{
return pt;
}
}
static long CountSubset( int [] val, int n)
{
long ans = powmod(2, n - 1);
Array.Sort(val);
for ( int i = 0; i < n; ++i)
{
int j = i + 1;
while (j < n && val[j] == val[i])
{
int r = n - 1 - j;
int l = i;
ans = (ans + arr[l + r,l]) % mod;
j++;
}
}
return ans;
}
public static void Main(String[] args)
{
Preprocess();
int []val = {2, 3, 2};
int n = val.Length;
Console.WriteLine(CountSubset(val, n));
}
}
|
Javascript
<script>
let mod = 1000000007;
let arr = [];
for (let i = 0;i<1001;i++){
arr[i] = [];
for (let j = 0;j<1001;j++){
arr[i][j] = 0;
}
}
function Preprocess()
{
arr[0][0] = 1;
for (let i = 1; i <= 1000; ++i) {
arr[i][0] = 1;
for (let j = 1; j < i; ++j) {
arr[i][j] = (arr[i - 1][j - 1] + arr[i - 1][j]) % mod;
}
arr[i][i] = 1;
}
}
function powmod( a, n)
{
if (!n)
return 1;
let pt = powmod(a, Math.floor(n / 2));
pt = (pt * pt) % mod;
if (n % 2)
return (pt * a) % mod;
else
return pt;
}
function CountSubset( val, n)
{
let ans = powmod(2, n - 1);
val.sort( function (a,b){ return a-b});
for (let i = 0; i < n; ++i) {
let j = i + 1;
while (j < n && val[j] == val[i]) {
let r = n - 1 - j;
let l = i;
ans = (ans + arr[l + r][l]) % mod;
j++;
}
}
return ans;
}
Preprocess();
let val = [ 2, 3, 2 ];
let n =val.length;
document.write( CountSubset(val, n), '<br>' );
</script>
|
Time Complexity: O(N2), as we are using nested loops for traversing N*N times, Where N is the number of elements in the array.
Auxiliary Complexity: O(1001*1001), as we are using extra space for the array arr.
Last Updated :
22 Jun, 2022
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...