Skip to content
Related Articles

Related Articles

    Improve Article
    Save Article
    Like Article

    Maximum average sum partition of an array

    • Difficulty Level : Hard
    • Last Updated : 22 Sep, 2021

    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 . 
     

    C++




    // CPP program for maximum average sum partition
    #include <bits/stdc++.h>
    using namespace std;
     
    #define MAX 1000
     
    double memo[MAX][MAX];
     
    // bottom up approach to calculate score
    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];
     
            // storing averages from starting to each 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; // atmost partitioning size
        cout << largestSumOfAverages(A, K) << endl;
        return 0;
    }

    Java




    // Java program for maximum average sum partition
    import java.util.Arrays;
    import java.util.Vector;
     
    class GFG
    {
     
        static int MAX = 1000;
        static double[][] memo = new double[MAX][MAX];
     
        // bottom up approach to calculate score
        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);
     
                // storing averages from starting to each i ;
                memo[i + 1][1] = sum / (i + 1);
            }
     
            return score(n, A, K);
        }
     
        // Driver code
        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));
     
        }
    }
     
    // This code is contributed by sanjeev2552

    Python3




    # Python3 program for maximum average sum partition
    MAX = 1000
     
    memo = [[0.0 for i in range(MAX)]
                 for i in range(MAX)]
     
    # bottom up approach to calculate score
    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]
     
            # storing averages from starting to each i ;
            memo[i + 1][1] = int(sum / (i + 1))
         
        return score(n, A, K)
     
    # Driver Code
    if __name__ == '__main__':
        A = [9, 1, 2, 3, 9]
        K = 3 # atmost partitioning size
        print(largestSumOfAverages(A, K))
         
    # This code is contributed by
    # Surendra_Gangwar

    C#




    // C# program for maximum average sum partition
    using System;
    using System.Collections.Generic;
     
    class GFG
    {
        static int MAX = 1000;
        static double[,] memo = new double[MAX, MAX];
     
        // bottom up approach to calculate score
        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];
     
                // storing averages from
                // starting to each i;
                memo[i + 1, 1] = sum / (i + 1);
            }
     
            return score(n, A, K);
        }
     
        // Driver code
        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));
        }
    }
     
    // This code is contributed by Rajput-Ji

    Javascript




    <script>
     
    // JavaScript program for maximum average sum partition
     
     
    let MAX = 1000;
     
    let memo = new Array(MAX).fill(0).map(() => new Array(MAX).fill(0));
     
    // bottom up approach to calculate score
    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];
     
            // storing averages from starting to each i ;
            memo[i + 1][1] = sum / (i + 1);
        }
        return score(n, A, K);
    }
     
     
    let A = [9, 1, 2, 3, 9];
    let K = 3; // atmost partitioning size
    document.write(largestSumOfAverages(A, K) + "<br>");
     
    </script>

     
     



    Output: 
    20

     

     

    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. 
     

     

    C++




    // CPP program for maximum average sum partition
    #include <bits/stdc++.h>
    using namespace std;
     
    double largestSumOfAverages(vector<int>& A, int K)
    {
        int n = A.size();
     
        // storing prefix sums
        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];
     
        // for each i to n storing averages
        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];
    }
     
    // Driver code
    int main()
    {
        vector<int> A = { 9, 1, 2, 3, 9 };
        int K = 3; // atmost partitioning size
        cout << largestSumOfAverages(A, K) << endl;
        return 0;
    }

    Java




    // Java program for maximum average sum partition
    import java.util.*;
     
    class GFG
    {
     
    static double largestSumOfAverages(int[] A, int K)
    {
        int n = A.length;
     
        // storing prefix sums
        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];
     
        // for each i to n storing averages
        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];
    }
     
    // Driver code
    public static void main(String[] args)
    {
        int []A = { 9, 1, 2, 3, 9 };
        int K = 3; // atmost partitioning size
        System.out.println(largestSumOfAverages(A, K));
    }
    }
     
    // This code is contributed by PrinciRaj1992

    Python3




    # Python3 program for maximum average
    # sum partition
    def largestSumOfAverages(A, K):
     
        n = len(A);
     
        # storing prefix sums
        pre_sum = [0] * (n + 1);
        pre_sum[0] = 0;
        for i in range(n):
            pre_sum[i + 1] = pre_sum[i] + A[i];
     
        # for each i to n storing averages
        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]);
     
    # Driver code
    A = [ 9, 1, 2, 3, 9 ];
    K = 3; # atmost partitioning size
    print(largestSumOfAverages(A, K));
     
    # This code is contributed by Rajput-Ji

    C#




    // C# program for maximum average sum partition
    using System;
    using System.Collections.Generic;
         
    class GFG
    {
    static double largestSumOfAverages(int[] A,
                                       int K)
    {
        int n = A.Length;
     
        // storing prefix sums
        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];
     
        // for each i to n storing averages
        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];
    }
     
    // Driver code
    public static void Main(String[] args)
    {
        int []A = { 9, 1, 2, 3, 9 };
        int K = 3; // atmost partitioning size
        Console.WriteLine(largestSumOfAverages(A, K));
    }
    }
     
    // This code is contributed by PrinciRaj1992

    Javascript




    <script>
    // javascript program for maximum average sum partition
     
        function largestSumOfAverages(A , K) {
            var n = A.length;
     
            // storing prefix sums
            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];
     
            // for each i to n storing averages
            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];
        }
     
        // Driver code
            var A = [ 9, 1, 2, 3, 9 ];
            var K = 3; // atmost partitioning size
            document.write(largestSumOfAverages(A, K));
     
    // This code is contributed by umadevi9616
    </script>
    Output: 
    20

     




    My Personal Notes arrow_drop_up

    Start Your Coding Journey Now!