Maximum average sum partition of an array
Last Updated :
20 Dec, 2022
Given an array, we partition a row of numbers A into at most K adjacent (non-empty) groups, then the score is the sum of the average of each group. What is the maximum score that can be scored?
Examples:
Input : A = { 9, 1, 2, 3, 9 }
K = 3
Output : 20
Explanation : We can partition A into [9], [1, 2, 3], [9]. The answer is 9 + (1 + 2 + 3) / 3 + 9 = 20.
We could have also partitioned A into [9, 1], [2], [3, 9]. That partition would lead to a score of 5 + 2 + 6 = 13, which is worse.
Input : A[] = { 1, 2, 3, 4, 5, 6, 7 }
K = 4
Output : 20.5
Explanation : We can partition A into [1, 2, 3, 4], [5], [6], [7]. The answer is 2.5 + 5 + 6 + 7 = 20.5.
A simple solution is to use recursion. An efficient solution is memorization where we keep the largest score upto k i.e. for 1, 2, 3… upto k;
Let memo[i][k] be the best score portioning A[i..n-1] into at most K parts. In the first group, we partition A[i..n-1] into A[i..j-1] and A[j..n-1], then our candidate partition has score average(i, j) + score(j, k-1)), where average(i, j) = (A[i] + A[i+1] + … + A[j-1]) / (j – i). We take the highest score of these.
In total, our recursion in the general case is :
memo[n][k] = max(memo[n][k], score(memo, i, A, k-1) + average(i, j))
for all i from n-1 to 1 .
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
#define MAX 1000
double memo[MAX][MAX];
double score( int n, vector< int >& A, int k)
{
if (memo[n][k] > 0)
return memo[n][k];
double sum = 0;
for ( int i = n - 1; i > 0; i--) {
sum += A[i];
memo[n][k] = max(memo[n][k], score(i, A, k - 1) +
sum / (n - i));
}
return memo[n][k];
}
double largestSumOfAverages(vector< int >& A, int K)
{
int n = A.size();
double sum = 0;
memset (memo, 0.0, sizeof (memo));
for ( int i = 0; i < n; i++) {
sum += A[i];
memo[i + 1][1] = sum / (i + 1);
}
return score(n, A, K);
}
int main()
{
vector< int > A = { 9, 1, 2, 3, 9 };
int K = 3;
cout << largestSumOfAverages(A, K) << endl;
return 0;
}
|
Java
import java.util.Arrays;
import java.util.Vector;
class GFG
{
static int MAX = 1000 ;
static double [][] memo = new double [MAX][MAX];
public static double score( int n, Vector<Integer> A, int k)
{
if (memo[n][k] > 0 )
return memo[n][k];
double sum = 0 ;
for ( int i = n - 1 ; i > 0 ; i--)
{
sum += A.elementAt(i);
memo[n][k] = Math.max(memo[n][k],
score(i, A, k - 1 ) +
sum / (n - i));
}
return memo[n][k];
}
public static double largestSumOfAverages(Vector<Integer> A, int K)
{
int n = A.size();
double sum = 0 ;
for ( int i = 0 ; i < memo.length; i++)
{
for ( int j = 0 ; j < memo[i].length; j++)
memo[i][j] = 0.0 ;
}
for ( int i = 0 ; i < n; i++)
{
sum += A.elementAt(i);
memo[i + 1 ][ 1 ] = sum / (i + 1 );
}
return score(n, A, K);
}
public static void main(String[] args)
{
Vector<Integer> A = new Vector<>(Arrays.asList( 9 , 1 , 2 , 3 , 9 ));
int K = 3 ;
System.out.println(largestSumOfAverages(A, K));
}
}
|
Python3
MAX = 1000
memo = [[ 0.0 for i in range ( MAX )]
for i in range ( MAX )]
def score(n, A, k):
if (memo[n][k] > 0 ):
return memo[n][k]
sum = 0
i = n - 1
while (i > 0 ):
sum + = A[i]
memo[n][k] = max (memo[n][k], score(i, A, k - 1 ) +
int ( sum / (n - i)))
i - = 1
return memo[n][k]
def largestSumOfAverages(A, K):
n = len (A)
sum = 0
for i in range (n):
sum + = A[i]
memo[i + 1 ][ 1 ] = int ( sum / (i + 1 ))
return score(n, A, K)
if __name__ = = '__main__' :
A = [ 9 , 1 , 2 , 3 , 9 ]
K = 3
print (largestSumOfAverages(A, K))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int MAX = 1000;
static double [,] memo = new double [MAX, MAX];
public static double score( int n,
List< int > A, int k)
{
if (memo[n, k] > 0)
return memo[n, k];
double sum = 0;
for ( int i = n - 1; i > 0; i--)
{
sum += A[i];
memo[n, k] = Math.Max(memo[n, k],
score(i, A, k - 1) +
sum / (n - i));
}
return memo[n, k];
}
public static double largestSumOfAverages(List< int > A,
int K)
{
int n = A.Count;
double sum = 0;
for ( int i = 0;
i < memo.GetLength(0); i++)
{
for ( int j = 0;
j < memo.GetLength(1); j++)
memo[i, j] = 0.0;
}
for ( int i = 0; i < n; i++)
{
sum += A[i];
memo[i + 1, 1] = sum / (i + 1);
}
return score(n, A, K);
}
public static void Main(String[] args)
{
int [] arr = {9, 1, 2, 3, 9};
List< int > A = new List< int >(arr);
int K = 3;
Console.WriteLine(largestSumOfAverages(A, K));
}
}
|
Javascript
<script>
let MAX = 1000;
let memo = new Array(MAX).fill(0).map(() => new Array(MAX).fill(0));
function score(n, A, k) {
if (memo[n][k] > 0)
return memo[n][k];
let sum = 0;
for (let i = n - 1; i > 0; i--) {
sum += A[i];
memo[n][k] = Math.max(memo[n][k], score(i, A, k - 1) +
sum / (n - i));
}
return memo[n][k];
}
function largestSumOfAverages(A, K) {
let n = A.length;
let sum = 0;
for (let i = 0; i < n; i++) {
sum += A[i];
memo[i + 1][1] = sum / (i + 1);
}
return score(n, A, K);
}
let A = [9, 1, 2, 3, 9];
let K = 3;
document.write(largestSumOfAverages(A, K) + "<br>" );
</script>
|
Above problem can now be easily understood as dynamic programming.
Let dp(i, k) be the best score partitioning A[i:j] into at most K parts. If the first group we partition A[i:j] into ends before j, then our candidate partition has score average(i, j) + dp(j, k-1)). Recursion in the general case is dp(i, k) = max(average(i, N), (average(i, j) + dp(j, k-1))). We can precompute the prefix sums for fast execution of out code.
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
double largestSumOfAverages(vector< int >& A, int K)
{
int n = A.size();
double pre_sum[n+1];
pre_sum[0] = 0;
for ( int i = 0; i < n; i++)
pre_sum[i + 1] = pre_sum[i] + A[i];
double dp[n] = {0};
double sum = 0;
for ( int i = 0; i < n; i++)
dp[i] = (pre_sum[n] - pre_sum[i]) / (n - i);
for ( int k = 0; k < K - 1; k++)
for ( int i = 0; i < n; i++)
for ( int j = i + 1; j < n; j++)
dp[i] = max(dp[i], (pre_sum[j] -
pre_sum[i]) / (j - i) + dp[j]);
return dp[0];
}
int main()
{
vector< int > A = { 9, 1, 2, 3, 9 };
int K = 3;
cout << largestSumOfAverages(A, K) << endl;
return 0;
}
|
Java
import java.util.*;
class GFG
{
static double largestSumOfAverages( int [] A, int K)
{
int n = A.length;
double []pre_sum = new double [n + 1 ];
pre_sum[ 0 ] = 0 ;
for ( int i = 0 ; i < n; i++)
pre_sum[i + 1 ] = pre_sum[i] + A[i];
double []dp = new double [n];
double sum = 0 ;
for ( int i = 0 ; i < n; i++)
dp[i] = (pre_sum[n] - pre_sum[i]) / (n - i);
for ( int k = 0 ; k < K - 1 ; k++)
for ( int i = 0 ; i < n; i++)
for ( int j = i + 1 ; j < n; j++)
dp[i] = Math.max(dp[i], (pre_sum[j] -
pre_sum[i]) / (j - i) + dp[j]);
return dp[ 0 ];
}
public static void main(String[] args)
{
int []A = { 9 , 1 , 2 , 3 , 9 };
int K = 3 ;
System.out.println(largestSumOfAverages(A, K));
}
}
|
Python3
def largestSumOfAverages(A, K):
n = len (A);
pre_sum = [ 0 ] * (n + 1 );
pre_sum[ 0 ] = 0 ;
for i in range (n):
pre_sum[i + 1 ] = pre_sum[i] + A[i];
dp = [ 0 ] * n;
sum = 0 ;
for i in range (n):
dp[i] = (pre_sum[n] -
pre_sum[i]) / (n - i);
for k in range (K - 1 ):
for i in range (n):
for j in range (i + 1 , n):
dp[i] = max (dp[i], (pre_sum[j] -
pre_sum[i]) /
(j - i) + dp[j]);
return int (dp[ 0 ]);
A = [ 9 , 1 , 2 , 3 , 9 ];
K = 3 ;
print (largestSumOfAverages(A, K));
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static double largestSumOfAverages( int [] A,
int K)
{
int n = A.Length;
double []pre_sum = new double [n + 1];
pre_sum[0] = 0;
for ( int i = 0; i < n; i++)
pre_sum[i + 1] = pre_sum[i] + A[i];
double []dp = new double [n];
for ( int i = 0; i < n; i++)
dp[i] = (pre_sum[n] - pre_sum[i]) / (n - i);
for ( int k = 0; k < K - 1; k++)
for ( int i = 0; i < n; i++)
for ( int j = i + 1; j < n; j++)
dp[i] = Math.Max(dp[i], (pre_sum[j] -
pre_sum[i]) / (j - i) + dp[j]);
return dp[0];
}
public static void Main(String[] args)
{
int []A = { 9, 1, 2, 3, 9 };
int K = 3;
Console.WriteLine(largestSumOfAverages(A, K));
}
}
|
Javascript
<script>
function largestSumOfAverages(A , K) {
var n = A.length;
var pre_sum = Array(n + 1).fill(-1);
pre_sum[0] = 0;
for ( var i = 0; i < n; i++)
pre_sum[i + 1] = pre_sum[i] + A[i];
var dp = Array(n).fill(-1);
var sum = 0;
for ( var i = 0; i < n; i++)
dp[i] = (pre_sum[n] - pre_sum[i]) / (n - i);
for (k = 0; k < K - 1; k++)
for (i = 0; i < n; i++)
for (j = i + 1; j < n; j++)
dp[i] = Math.max(dp[i], (pre_sum[j] - pre_sum[i]) / (j - i) + dp[j]);
return dp[0];
}
var A = [ 9, 1, 2, 3, 9 ];
var K = 3;
document.write(largestSumOfAverages(A, K));
</script>
|
Time Complexity: O(n2*K)
Auxiliary Space: O(n)
Share your thoughts in the comments
Please Login to comment...