Divide an array into K subarray with the given condition
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) = 19
Input: 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++
#include <bits/stdc++.h>
using namespace std;
int divideArray( int arr[], int n, int k)
{
int dp[500][500] = { 0 };
k -= 1;
for ( int i = n - 1; i >= 0; i--) {
for ( int j = 0; j <= k; j++) {
dp[i][j] = INT_MAX;
int max_ = -1, sum = 0;
for ( int l = i; l < n; l++) {
max_ = max(max_, arr[l]);
sum += arr[l];
int diff = (l - i + 1) * max_ - sum;
if (j > 0)
dp[i][j]
= min(dp[i][j],
diff + dp[l + 1][j - 1]);
else
dp[i][j] = diff;
}
}
}
return dp[0][k];
}
int 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
class GFG
{
static int divideArray( int arr[], int n, int k)
{
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 ;
for (i = n - 1 ; i >= 0 ; i--)
{
for (j = 0 ; j <= k; j++)
{
dp[i][j] = Integer.MAX_VALUE;
int max_ = - 1 , sum = 0 ;
for ( int l = i; l < n; l++)
{
max_ = Math.max(max_, arr[l]);
sum += arr[l];
int diff = (l - i + 1 ) * max_ - sum;
if (j > 0 )
dp[i][j] = Math.min(dp[i][j], diff +
dp[l + 1 ][j - 1 ]);
else
dp[i][j] = diff;
}
}
}
return dp[ 0 ][k];
}
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));
}
}
|
Python3
def divideArray(arr, n, k):
dp = [[ 0 for i in range ( 500 )]
for i in range ( 500 )]
k - = 1
for i in range (n - 1 , - 1 , - 1 ):
for j in range ( 0 , k + 1 ):
dp[i][j] = 10 * * 9
max_ = - 1
summ = 0
for l in range (i, n):
max_ = max (max_, arr[l])
summ + = arr[l]
diff = (l - i + 1 ) * max_ - summ
if (j > 0 ):
dp[i][j] = min (dp[i][j], diff +
dp[l + 1 ][j - 1 ])
else :
dp[i][j] = diff
return dp[ 0 ][k]
arr = [ 2 , 9 , 5 , 4 , 8 , 3 , 6 ]
n = len (arr)
k = 2
print (divideArray(arr, n, k))
|
C#
using System;
class GFG
{
static int divideArray( int []arr, int n, int k)
{
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;
for (i = n - 1; i >= 0; i--)
{
for (j = 0; j <= k; j++)
{
dp[i, j] = int .MaxValue;
int max_ = -1, sum = 0;
for ( int l = i; l < n; l++)
{
max_ = Math.Max(max_, arr[l]);
sum += arr[l];
int diff = (l - i + 1) * max_ - sum;
if (j > 0)
dp[i, j] = Math.Min(dp[i, j], diff +
dp[l + 1, j - 1]);
else
dp[i, j] = diff;
}
}
}
return dp[0, k];
}
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));
}
}
|
Javascript
<script>
function divideArray(arr, n, k)
{
var dp = Array.from(Array(500), ()=> Array(500).fill(0));
k -= 1;
for ( var i = n - 1; i >= 0; i--) {
for ( var j = 0; j <= k; j++) {
dp[i][j] = 1000000000;
var max_ = -1, sum = 0;
for ( var l = i; l < n; l++) {
max_ = Math.max(max_, arr[l]);
sum += arr[l];
var diff = (l - i + 1) * max_ - sum;
if (j > 0)
dp[i][j]
= Math.min(dp[i][j],
diff + dp[l + 1][j - 1]);
else
dp[i][j] = diff;
}
}
}
return dp[0][k];
}
var arr = [2, 9, 5, 4, 8, 3, 6 ];
var n = arr.length;
var k = 2;
document.write( divideArray(arr, n, k) + "<br>" );
</script>
|
Time Complexity: O(n*n*k) , n is the size of array
Auxiliary Space: O(n*k)
Last Updated :
29 Mar, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...