Divide an array into K subarray with the given condition - GeeksforGeeks

06 May, 2021
Given an array arr[] and an integer K. The task is to divide the array into K parts ( subarray ) such that the sum of the values of all subarray is minimum.The value of every subarray is defined as:  
Take the maximum from that subarray.
Subtract each element of the subarray with the maximum.
Take the sum of all the values after subtraction.
The task is to minimize the sum of the values after dividing the array into K parts.Examples:  
Input: arr[] = { 2, 9, 5, 4, 8, 3, 6 }, K = 2 Output: 19 Explanation: The two groups are : {2} with max = 2 and {9, 5, 4, 8, 3, 6} with max=9, sum of difference of first group = 2 – 2 = 0, sum of difference of second group = (9-9) + (9-5) + (9-4) + (9-8) + (9-3) + (9-6) = 19Input: arr[] = { 12, 20, 30, 14, 25}, K = 3 Output: 19  
 
Approach: The brute-force solution will be to try all the possible partitions and take the minimum overall. Although this solution is exponential in time. In the recursive solution, there are many overlapping sub-problems that can be optimised using dynamic programming.So, We can form a basic recursive formula and that computes every possible solution and finds the best possible solution. We can see that the recursive solution has many overlapping sub-problems we can reduce the complexity using Dynamic programming.Recursive formula: F(i, K) = { min of all values such that j < i [ max(Arr[i..j]) * (i – j + 1) – Sum(A[i...j] ] } + F(j, K-1) The bottom-up approach can be used to compute the values of sub-problems first and store them.Here dp[i][j] defines the minimum value that can be obtained if the array is starting from index i and have j partition.So, the answer to the problems will be dp[0][K], array starting at 0 and having K partitions.Below is the implementation of the above approach:  
C++
Java
Python3
C#
Javascript
// C++ implementation of the above approach #include <bits/stdc++.h>using namespace std; // Function to divide an array into k// parts such that the sum of difference// of every element with the maximum element// of that part is minimumint divideArray(int arr[], int n, int k){    // Dp to store the values    int dp[500][500] = { 0 };     k -= 1;     // Fill up the dp table    for (int i = n - 1; i >= 0; i--) {        for (int j = 0; j <= k; j++) {            // Intitilize maximum value            dp[i][j] = INT_MAX;             // Max element and the sum            int max_ = -1, sum = 0;             // Run a loop from i to n            for (int l = i; l < n; l++) {                // Find the maximum number                // from i to l and the sum                // from i to l                max_ = max(max_, arr[l]);                sum += arr[l];                 // Find the sum of difference                // of every element with the                // maximum element                int diff = (l - i + 1) * max_ - sum;                 // If the array can be divided                if (j > 0)                    dp[i][j]                        = min(dp[i][j],                              diff + dp[l + 1][j - 1]);                else                    dp[i][j] = diff;            }        }    }     // Returns the minimum sum    // in K parts    return dp[0][k];} // Driver codeint main(){    int arr[] = { 2, 9, 5, 4, 8, 3, 6 };    int n = sizeof(arr) / sizeof(int);    int k = 2;     cout << divideArray(arr, n, k) << "\n";     return 0;}
// Java implementation of the above approachclass GFG{         // Function to divide an array into k    // parts such that the sum of difference    // of every element with the maximum element    // of that part is minimum    static int divideArray(int arr[], int n, int k)    {        // Dp to store the values        int dp[][] = new int[500][500];                 int i, j;                 for(i = 0; i < 500; i++)            for(j = 0; j < 500; j++)                dp[i][j] = 0;                         k -= 1;             // Fill up the dp table        for (i = n - 1; i >= 0; i--)        {            for (j = 0; j <= k; j++)            {                                 // Intitilize maximum value                dp[i][j] = Integer.MAX_VALUE;                     // Max element and the sum                int max_ = -1, sum = 0;                     // Run a loop from i to n                for (int l = i; l < n; l++)                {                    // Find the maximum number                    // from i to l and the sum                    // from i to l                    max_ = Math.max(max_, arr[l]);                    sum += arr[l];                         // Find the sum of difference                    // of every element with the                    // maximum element                    int diff = (l - i + 1) * max_ - sum;                         // If the array can be divided                    if (j > 0)                        dp[i][j] = Math.min(dp[i][j], diff +                                            dp[l + 1][j - 1]);                    else                        dp[i][j] = diff;                }            }        }             // Returns the minimum sum        // in K parts        return dp[0][k];    }         // Driver code    public static void main (String[] args)    {        int arr[] = { 2, 9, 5, 4, 8, 3, 6 };        int n = arr.length;        int k = 2;             System.out.println(divideArray(arr, n, k));    }} // This code is contributed by AnkitRai01
# Python3 implementation of the above approach # Function to divide an array into k# parts such that the summ of difference# of every element with the maximum element# of that part is minimumdef divideArray(arr, n, k):         # Dp to store the values    dp = [[0 for i in range(500)]             for i in range(500)]     k -= 1     # Fill up the dp table    for i in range(n - 1, -1, -1):        for j in range(0, k + 1):                         # Intitilize maximum value            dp[i][j] = 10**9             # Max element and the summ            max_ = -1            summ = 0             # Run a loop from i to n            for l in range(i, n):                                 # Find the maximum number                # from i to l and the summ                # from i to l                max_ = max(max_, arr[l])                summ += arr[l]                 # Find the summ of difference                # of every element with the                # maximum element                diff = (l - i + 1) * max_ - summ                 # If the array can be divided                if (j > 0):                    dp[i][j]= min(dp[i][j], diff +                                  dp[l + 1][j - 1])                else:                    dp[i][j] = diff     # Returns the minimum summ    # in K parts    return dp[0][k] # Driver codearr = [2, 9, 5, 4, 8, 3, 6]n = len(arr)k = 2 print(divideArray(arr, n, k)) # This code is contributed by Mohit Kumar
// C# implementation of above approachusing System; class GFG{         // Function to divide an array into k    // parts such that the sum of difference    // of every element with the maximum element    // of that part is minimum    static int divideArray(int []arr, int n, int k)    {        // Dp to store the values        int [,]dp = new int[500, 500];                 int i, j;                 for(i = 0; i < 500; i++)            for(j = 0; j < 500; j++)                dp[i, j] = 0;                         k -= 1;             // Fill up the dp table        for (i = n - 1; i >= 0; i--)        {            for (j = 0; j <= k; j++)            {                                 // Intitilize maximum value                dp[i, j] = int.MaxValue;                     // Max element and the sum                int max_ = -1, sum = 0;                     // Run a loop from i to n                for (int l = i; l < n; l++)                {                    // Find the maximum number                    // from i to l and the sum                    // from i to l                    max_ = Math.Max(max_, arr[l]);                    sum += arr[l];                         // Find the sum of difference                    // of every element with the                    // maximum element                    int diff = (l - i + 1) * max_ - sum;                         // If the array can be divided                    if (j > 0)                        dp[i, j] = Math.Min(dp[i, j], diff +                                            dp[l + 1, j - 1]);                    else                        dp[i, j] = diff;                }            }        }             // Returns the minimum sum        // in K parts        return dp[0, k];    }         // Driver code    public static void Main (String[] args)    {        int []arr = { 2, 9, 5, 4, 8, 3, 6 };        int n = arr.Length;        int k = 2;             Console.WriteLine(divideArray(arr, n, k));    }} // This code is contributed by 29AjayKumar
<script> // Javascript implementation of the above approach // Function to divide an array into k// parts such that the sum of difference// of every element with the maximum element// of that part is minimumfunction divideArray(arr, n, k){    // Dp to store the values    var dp = Array.from(Array(500), ()=> Array(500).fill(0));     k -= 1;     // Fill up the dp table    for (var i = n - 1; i >= 0; i--) {        for (var j = 0; j <= k; j++) {            // Intitilize maximum value            dp[i][j] = 1000000000;             // Max element and the sum            var max_ = -1, sum = 0;             // Run a loop from i to n            for (var l = i; l < n; l++) {                // Find the maximum number                // from i to l and the sum                // from i to l                max_ = Math.max(max_, arr[l]);                sum += arr[l];                 // Find the sum of difference                // of every element with the                // maximum element                var diff = (l - i + 1) * max_ - sum;                 // If the array can be divided                if (j > 0)                    dp[i][j]                        = Math.min(dp[i][j],                              diff + dp[l + 1][j - 1]);                else                    dp[i][j] = diff;            }        }    }     // Returns the minimum sum    // in K parts    return dp[0][k];} // Driver codevar arr = [2, 9, 5, 4, 8, 3, 6 ];var n = arr.length;var k = 2;document.write( divideArray(arr, n, k) + "<br>"); </script>
19
 
mohit kumar 29
ankthon
29AjayKumar
rrrtnx
subarray
tail-recursion
Arrays
Dynamic Programming
Recursion
Arrays
Dynamic Programming
Recursion
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Maximum and minimum of an array using minimum number of comparisons
Stack Data Structure (Introduction and Program)
Top 50 Array Coding Problems for Interviews
Multidimensional Arrays in Java
Introduction to Arrays
0-1 Knapsack Problem | DP-10
Program for Fibonacci numbers
Longest Common Subsequence | DP-4
Bellman–Ford Algorithm | DP-23
Floyd Warshall Algorithm | DP-16