Divide an array into K subarray with the given condition
Last Updated :
29 Mar, 2023
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++
// 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 minimum
int 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 code
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
// Java implementation of the above approach
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] = 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
# 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 minimum
def 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 code
arr = [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#
// C# implementation of above approach
using 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
JavaScript
<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 minimum
function 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 code
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)
Similar Reads
Divide an array into k subarrays with minimum cost II Given an array of integers arr[] of length n and two positive integers kk and len. The cost of an array is the value of its first element. For example, the cost of [2,3,4] is 2 and the cost of [4,1,2] is 4. You have to divide arr[] into k disjoint contiguous subarrays such that the difference betwee
11 min read
Construct an Array having K Subarrays with all distinct elements Given integers N and K, the task is to construct an array arr[] of size N using numbers in the range [1, N] such that it has K sub-arrays whose all the elements are distinct. Note: If there are multiple possible answers return any of them. Examples: Input: N = 5, K = 8Output: {1, 2, 3, 3, 3}Explanat
7 min read
Divide array into two arrays which does not contain any pair with sum K Given an array arr[] consisting of N non-negative distinct integers and an integer K, the task is to distribute the array in two arrays such that both the arrays does not contain a pair with sum K. Examples: Input: arr[] = {1, 0, 2, 3, 4, 7, 8, 9}, K = 4Output: 3, 2, 4, 7, 8, 9 0, 1 Explanation: Pai
6 min read
Check if an array can be split into subarrays with GCD exceeding K Given an array arr[] of N integers and a positive integer K, the task is to check if it is possible to split this array into distinct contiguous subarrays such that the Greatest Common Divisor of all elements of each subarray is greater than K. Note: Each array element can be a part of exactly one s
5 min read
Count Subarrays With Sum Divisible By K Given an array arr[] and an integer k, the task is to count all subarrays whose sum is divisible by k.Examples: Input: arr[] = [4, 5, 0, -2, -3, 1], k = 5Output: 7Explanation: There are 7 subarrays whose sum is divisible by 5: [4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3] and [
9 min read