Given an array arr[] of N integer elements, the task is to find the sum of the average of all subsets of this array.
Example:
Input : arr[] = [2, 3, 5]
Output : 23.33
Explanation : Subsets with their average are,
[2] average = 2/1 = 2
[3] average = 3/1 = 3
[5] average = 5/1 = 5
[2, 3] average = (2+3)/2 = 2.5
[2, 5] average = (2+5)/2 = 3.5
[3, 5] average = (3+5)/2 = 4
[2, 3, 5] average = (2+3+5)/3 = 3.33
Sum of average of all subset is,
2 + 3 + 5 + 2.5 + 3.5 + 4 + 3.33 = 23.33
Naive approach: A naive solution is to iterate through all possible subsets, get an average of all of them and then add them one by one, but this will take exponential time and will be infeasible for bigger arrays.
We can get a pattern by taking an example,
arr = [a0, a1, a2, a3]
sum of average =
a0/1 + a1/1 + a2/2 + a3/1 +
(a0+a1)/2 + (a0+a2)/2 + (a0+a3)/2 + (a1+a2)/2 +
(a1+a3)/2 + (a2+a3)/2 +
(a0+a1+a2)/3 + (a0+a2+a3)/3 + (a0+a1+a3)/3 +
(a1+a2+a3)/3 +
(a0+a1+a2+a3)/4
If S = (a0+a1+a2+a3), then above expression
can be rearranged as below,
sum of average = (S)/1 + (3*S)/2 + (3*S)/3 + (S)/4
The coefficient with numerators can be explained as follows, suppose we are iterating over subsets with K elements then denominator will be K and the numerator will be r*S, where ‘r’ denotes the number of times a particular array element will be added while iterating over subsets of the same size. By inspection, we can see that r will be nCr(N – 1, n – 1) because after placing one element in summation, we need to choose (n – 1) elements from (N – 1) elements, so each element will have a frequency of nCr(N – 1, n – 1) while considering subsets of the same size, as all elements are taking part in summation equal number of times, this will the frequency of S also and will be the numerator in the final expression.
In the below code nCr is implemented using dynamic programming method, you can read more about that here,
C++
#include <bits/stdc++.h>
using namespace std;
int nCr( int n, int k)
{
int C[n + 1][k + 1];
int i, j;
for (i = 0; i <= n; i++) {
for (j = 0; j <= min(i, k); j++) {
if (j == 0 || j == i)
C[i][j] = 1;
else
C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
}
}
return C[n][k];
}
double resultOfAllSubsets( int arr[], int N)
{
double result = 0.0;
int sum = 0;
for ( int i = 0; i < N; i++)
sum += arr[i];
for ( int n = 1; n <= N; n++)
result += ( double )(sum * (nCr(N - 1, n - 1))) / n;
return result;
}
int main()
{
int arr[] = { 2, 3, 5, 7 };
int N = sizeof (arr) / sizeof ( int );
cout << resultOfAllSubsets(arr, N) << endl;
return 0;
}
|
Java
import java.io.*;
class GFG {
static int nCr( int n, int k)
{
int C[][] = new int [n + 1 ][k + 1 ];
int i, j;
for (i = 0 ; i <= n; i++) {
for (j = 0 ; j <= Math.min(i, k); j++) {
if (j == 0 || j == i)
C[i][j] = 1 ;
else
C[i][j] = C[i - 1 ][j - 1 ] + C[i - 1 ][j];
}
}
return C[n][k];
}
static double resultOfAllSubsets( int arr[], int N)
{
double result = 0.0 ;
int sum = 0 ;
for ( int i = 0 ; i < N; i++)
sum += arr[i];
for ( int n = 1 ; n <= N; n++)
result += ( double )(sum * (nCr(N - 1 , n - 1 ))) / n;
return result;
}
public static void main(String[] args)
{
int arr[] = { 2 , 3 , 5 , 7 };
int N = arr.length;
System.out.println(resultOfAllSubsets(arr, N));
}
}
|
Python3
def nCr(n, k):
C = [[ 0 for i in range (k + 1 )]
for j in range (n + 1 )]
for i in range (n + 1 ):
for j in range ( min (i, k) + 1 ):
if (j = = 0 or j = = i):
C[i][j] = 1
else :
C[i][j] = C[i - 1 ][j - 1 ] + C[i - 1 ][j]
return C[n][k]
def resultOfAllSubsets(arr, N):
result = 0.0
sum = 0
for i in range (N):
sum + = arr[i]
for n in range ( 1 , N + 1 ):
result + = ( sum * (nCr(N - 1 , n - 1 ))) / n
return result
arr = [ 2 , 3 , 5 , 7 ]
N = len (arr)
print (resultOfAllSubsets(arr, N))
|
C#
using System;
class GFG {
static int nCr( int n, int k)
{
int [, ] C = new int [n + 1, k + 1];
int i, j;
for (i = 0; i <= n; i++) {
for (j = 0; j <= Math.Min(i, k); j++)
{
if (j == 0 || j == i)
C[i, j] = 1;
else
C[i, j] = C[i - 1, j - 1] + C[i - 1, j];
}
}
return C[n, k];
}
static double resultOfAllSubsets( int [] arr, int N)
{
double result = 0.0;
int sum = 0;
for ( int i = 0; i < N; i++)
sum += arr[i];
for ( int n = 1; n <= N; n++)
result += ( double )(sum * (nCr(N - 1, n - 1))) / n;
return result;
}
public static void Main()
{
int [] arr = { 2, 3, 5, 7 };
int N = arr.Length;
Console.WriteLine(resultOfAllSubsets(arr, N));
}
}
|
Javascript
<script>
function nCr(n, k)
{
let C = new Array(n + 1);
for (let i = 0; i <= n; i++)
{
C[i] = new Array(k + 1);
for (let j = 0; j <= k; j++)
{
C[i][j] = 0;
}
}
let i, j;
for (i = 0; i <= n; i++) {
for (j = 0; j <= Math.min(i, k); j++) {
if (j == 0 || j == i)
C[i][j] = 1;
else
C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
}
}
return C[n][k];
}
function resultOfAllSubsets(arr, N)
{
let result = 0.0;
let sum = 0;
for (let i = 0; i < N; i++)
sum += arr[i];
for (let n = 1; n <= N; n++)
result += (sum * (nCr(N - 1, n - 1))) / n;
return result;
}
let arr = [ 2, 3, 5, 7 ];
let N = arr.length;
document.write(resultOfAllSubsets(arr, N));
</script>
|
PHP
<?php
function nCr( $n , $k )
{
$C [ $n + 1][ $k + 1] = 0;
$i ; $j ;
for ( $i = 0; $i <= $n ; $i ++)
{
for ( $j = 0; $j <= min( $i , $k ); $j ++)
{
if ( $j == 0 || $j == $i )
$C [ $i ][ $j ] = 1;
else
$C [ $i ][ $j ] = $C [ $i - 1][ $j - 1] +
$C [ $i - 1][ $j ];
}
}
return $C [ $n ][ $k ];
}
function resultOfAllSubsets( $arr , $N )
{
$result = 0.0;
$sum = 0;
for ( $i = 0; $i < $N ; $i ++)
$sum += $arr [ $i ];
for ( $n = 1; $n <= $N ; $n ++)
$result += (( $sum * (nCr( $N - 1,
$n - 1))) / $n );
return $result ;
}
$arr = array ( 2, 3, 5, 7 );
$N = sizeof( $arr ) / sizeof( $arr [0]);
echo resultOfAllSubsets( $arr , $N ) ;
?>
|
Time Complexity: O(n3)
Auxiliary Space: O(n2)
Efficient Approach : Space Optimization O(1)
To optimize the space complexity of the above approach, we can use a more efficient approach that avoids the need for the entire matrix C[][] to store binomial coefficients. Instead, we can use a combination formula to calculate the binomial coefficient directly when needed.
Implementation steps:
- Iterate over the elements of the array and calculate the sum of all elements.
- Iterate over each subset size from 1 to N.
- Inside the loop, calculate the average of the sum of elements multiplied by the binomial coefficient for the subset size. Add the calculated average to the result.
- Return the final result.
Implementation:
C++
#include <iostream>
using namespace std;
int binomialCoeff( int n, int k)
{
int res = 1;
if (k > n - k)
k = n - k;
for ( int i = 0; i < k; i++)
{
res *= (n - i);
res /= (i + 1);
}
return res;
}
double resultOfAllSubsets( int arr[], int N)
{
double result = 0.0;
int sum = 0;
for ( int i = 0; i < N; i++)
sum += arr[i];
for ( int n = 1; n <= N; n++)
result += ( double )(sum * binomialCoeff(N - 1, n - 1)) / n;
return result;
}
int main()
{
int arr[] = { 2, 3, 5, 7 };
int N = sizeof (arr) / sizeof ( int );
cout << resultOfAllSubsets(arr, N) << endl;
return 0;
}
|
Java
import java.util.Arrays;
public class Main {
static int binomialCoeff( int n, int k) {
int res = 1 ;
if (k > n - k)
k = n - k;
for ( int i = 0 ; i < k; i++) {
res *= (n - i);
res /= (i + 1 );
}
return res;
}
static double resultOfAllSubsets( int arr[], int N) {
double result = 0.0 ;
int sum = 0 ;
for ( int i = 0 ; i < N; i++)
sum += arr[i];
for ( int n = 1 ; n <= N; n++)
result += ( double ) (sum * binomialCoeff(N - 1 , n - 1 )) / n;
return result;
}
public static void main(String[] args) {
int arr[] = { 2 , 3 , 5 , 7 };
int N = arr.length;
System.out.println(resultOfAllSubsets(arr, N));
}
}
|
Python3
def binomialCoeff(n, k):
res = 1
if k > n - k:
k = n - k
for i in range (k):
res * = (n - i)
res / / = (i + 1 )
return res
def resultOfAllSubsets(arr, N):
result = 0.0
sum_val = 0
for i in range (N):
sum_val + = arr[i]
for n in range ( 1 , N + 1 ):
result + = (sum_val * binomialCoeff(N - 1 , n - 1 )) / n
return result
arr = [ 2 , 3 , 5 , 7 ]
N = len (arr)
print (resultOfAllSubsets(arr, N))
|
C#
using System;
public class MainClass
{
static int BinomialCoeff( int n, int k)
{
int res = 1;
if (k > n - k)
k = n - k;
for ( int i = 0; i < k; i++)
{
res *= (n - i);
res /= (i + 1);
}
return res;
}
static double ResultOfAllSubsets( int [] arr, int N)
{
double result = 0.0;
int sumVal = 0;
for ( int i = 0; i < N; i++)
sumVal += arr[i];
for ( int n = 1; n <= N; n++)
result += ( double )(sumVal * BinomialCoeff(N - 1, n - 1)) / n;
return result;
}
public static void Main()
{
int [] arr = { 2, 3, 5, 7 };
int N = arr.Length;
Console.WriteLine(ResultOfAllSubsets(arr, N));
}
}
|
Javascript
function binomialCoeff(n, k) {
let res = 1;
if (k > n - k)
k = n - k;
for (let i = 0; i < k; i++) {
res *= (n - i);
res /= (i + 1);
}
return res;
}
function resultOfAllSubsets(arr) {
let result = 0.0;
let sum = arr.reduce((acc, val) => acc + val, 0);
for (let n = 1; n <= arr.length; n++) {
result += (sum * binomialCoeff(arr.length - 1, n - 1)) / n;
}
return result;
}
const arr = [2, 3, 5, 7];
console.log(resultOfAllSubsets(arr));
|
Output
63.75
Time Complexity: O(n^2)
Auxiliary Space: O(1)
If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!