Minimize sum of differences between maximum and minimum elements present in K subsets
Last Updated :
21 Feb, 2023
Given an array arr[] of size N and an integer K, the task is to minimize the sum of the difference between the maximum and minimum element of each subset by splitting the array into K subsets such that each subset consists of unique array elements only.
Examples:
Input: arr[] = { 6, 3, 8, 1, 3, 1, 2, 2 }, K = 4 Output: 6 Explanation: One of the optimal ways to split the array into K(= 4) subsets are { { 1, 2 }, { 2, 3 }, { 6, 8 }, { 1, 4 } }. Sum of difference of maximum and minimum element present in each subset = { (2 - 1) + (3 - 2) + (8 - 6) + (3 - 1) } = 6. Therefore, the required output is 6
Input: arr[] = { 2, 2, 1, 1 }, K = 1 Output: -1
Approach: The problem can be solved using Dynamic Programming with bitmasking. Following are the recurrence relations:
mask: ith bit of mask checks if array element is already selected in a subset or not. l: index of last element selected in a subset. j: index of current element selected in a subset.
If count of set bits in mask mod (N / K) == 1: dp[mask][l] = min(dp[mask][l], dp[mask ^ (1 << l)][j])
Otherwise, dp[mask][j] = min(dp[mask][j], dp[mask ^ (1 << j)][l] + nums[l] - nums[j])
Follow the steps below to solve the problem:
- Iterate over all possible values of mask, i.e. [0, 2N - 1]
- Initialize an array, say n_z_bits[], to store the count of elements already selected in subsets.
- Use the above recurrence relation and fill all possible dp states of the recurrence relation.
- Finally, print the minimum elements from dp[(1 << N ) - 1].
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
// Function to minimize the sum of
// difference between maximums and
// minimums of K subsets of an array
int MinimizeSum(vector<int>& nums, int k)
{
// Stores count of elements
// in an array
int n = nums.size();
// Base Case
if (k == n)
return 0;
// Initialize DP[][] array
int inf = 1e9;
vector<vector<int> > dp(1 << n, vector<int>(n, inf));
// Sort the array
sort(nums.begin(), nums.end());
// Mark i-th element as not selected
for (int i = 0; i < n; i++) {
dp[1 << i][i] = 0;
}
// Iterate over all possible
// values of mask
for (int mask = 0; mask < (1 << n); mask++) {
// Store count of set bits
// in mask
vector<int> n_z_bits;
// Store index of element which is
// already selected in a subset
for (int i = 0; i < n; i++) {
if ((mask >> i) & 1) {
n_z_bits.push_back(i);
}
}
// If count of set bits in mask mod (n // k) equal
// to 1
if (n_z_bits.size() % (n / k) == 1) {
for (int i = 0; i < n_z_bits.size(); i++) {
for (int j = i + 1; j < n_z_bits.size();
j++) {
int temp = dp[mask ^ (1 << n_z_bits[j])]
[n_z_bits[i]];
dp[mask][n_z_bits[j]]
= min(dp[mask][n_z_bits[j]], temp);
}
}
}
else {
for (int i = 0; i < n_z_bits.size(); i++) {
for (int j = i + 1; j < n_z_bits.size();
j++) {
if (nums[n_z_bits[i]]
!= nums[n_z_bits[j]]) {
// Check if l-th element
// is already selected or not
int
mask_t
= mask ^ (1 << n_z_bits[j]);
int temp
= (dp[mask_t][n_z_bits[i]]
+ nums[n_z_bits[i]]
- nums[n_z_bits[j]]);
// Update dp[mask][l]
dp[mask][n_z_bits[j]] = min(
dp[mask][n_z_bits[j]], temp);
}
}
}
}
}
// Return minimum element
// from dp[(1 << N) - 1]
int minVal = inf;
for (int i = 0; i < n; i++) {
minVal = min(minVal, dp[(1 << n) - 1][i]);
}
// If dp[-1] is inf then the
// partition is not possible
if (minVal == inf) {
return -1;
}
else {
return 999999999- minVal;
}
}
// Driver Code
int main()
{
// Given array
vector<int> arr = { 6, 3, 8, 1, 3, 1, 2, 2 };
int k = 4;
// Function call
cout << MinimizeSum(arr, k) << endl;
return 0;
}
// This code is contributed by lokeshpotta20.
Java
import java.util.*;
public class GFG
{
// Function to minimize the sum of
// difference between maximums and
// minimums of K subsets of an array
public static int MinimizeSum(List<Integer> nums, int k)
{
// Stores count of elements
// in an array
int n = nums.size();
//Base Case
if (k == n) {
return 0;
}
// Initialize DP[][] array
int inf = 1_000_000_000;
int[][] dp = new int[1 << n][n];
for (int[] row : dp) {
java.util.Arrays.fill(row, inf);
}
// Sort the array
Collections.sort(nums);
// Mark i-th element as not selected
for (int i = 0; i < n; i++) {
dp[1 << i][i] = 0;
}
// Iterate over all possible
// values of mask
for (int mask = 0; mask < (1 << n); mask++)
{
// Store count of set bits
// in mask
List<Integer> n_z_bits = new ArrayList<>();
// Store index of element which is
// already selected in a subset
for (int i = 0; i < n; i++) {
if ((mask >> i & 1) == 1) {
n_z_bits.add(i);
}
}
// If count of set bits in mask mod (n // k) equal
// to 1
if (n_z_bits.size() % (n / k) == 1) {
for (int i = 0; i < n_z_bits.size(); i++) {
for (int j = i + 1; j < n_z_bits.size(); j++) {
int temp = dp[mask ^ (1 << n_z_bits.get(j))][n_z_bits.get(i)];
dp[mask][n_z_bits.get(j)] = Math.min(dp[mask][n_z_bits.get(j)], temp);
}
}
} else {
for (int i = 0; i < n_z_bits.size(); i++) {
for (int j = i + 1; j < n_z_bits.size(); j++) {
if (nums.get(n_z_bits.get(i)) != nums.get(n_z_bits.get(j)))
{
// Check if l-th element
// is already selected or not
int maskT = mask ^ (1 << n_z_bits.get(j));
int temp = (dp[maskT][n_z_bits.get(i)] + nums.get(n_z_bits.get(i)) - nums.get(n_z_bits.get(j)));
// Update dp[mask][l]
dp[mask][n_z_bits.get(j)] = Math.min(dp[mask][n_z_bits.get(j)], temp);
}
}
}
}
}
// Return minimum element
// from dp[(1 << N) - 1]
int minVal = inf;
// If dp[-1] is inf then the
// partition is not possible
for (int i = 0; i < n; i++) {
minVal = Math.min(minVal, dp[(1 << n) - 1][i]);
}
if (minVal == inf) {
return -1;
} else {
return 999999999 - minVal;
}
}
public static void main(String[] args) {
List<Integer> arr = new ArrayList<>();
arr.add(6);arr.add(3);arr.add(8);arr.add(1);
arr.add(3);arr.add(1);arr.add(2);arr.add(2);
int k = 4;
System.out.println(MinimizeSum(arr,k));
}
}
// This code is contributed by anskalyan3.
Python3
# Python program to implement
# the above approach
from itertools import permutations
from itertools import combinations
# Function to minimize the sum of
# difference between maximums and
# minimums of K subsets of an array
def MinimizeSum(nums, k):
# Stores count of elements
# in an array
n = len(nums)
# Base Case
if k == n:
return 0
# Initialize DP[][] array
dp = [[float("inf")] * n for _ in range(1 << n)]
# Sort the array
nums.sort()
# Mark i-th element
# as not selected
for i in range(n):
dp[1 << i][i] = 0
# Iterate over all possible
# values of mask
for mask in range(1 << n):
# Store count of set bits
# in mask
n_z_bits = []
# Store index of element which is
# already selected in a subset
for p, c in enumerate(bin(mask)):
if c == "1":
temp = len(bin(mask)) - p - 1
n_z_bits.append(temp)
# If count of set bits in mask
# mod (n // k) equal to 1
if len(n_z_bits) % (n//k) == 1:
for j, l in permutations(n_z_bits, 2):
temp = dp[mask ^ (1 << l)][j]
dp[mask][l] = min(dp[mask][l], temp)
else:
for j, l in combinations(n_z_bits, 2):
if nums[j] != nums[l]:
# Check if l-th element
# is already selected or not
mask_t = mask ^ (1 << l)
temp = (dp[mask_t][j] +
nums[j] - nums[l])
# Update dp[mask][l]
dp[mask][l] = min(dp[mask][l],
temp)
# Return minimum element
# from dp[(1 << N) - 1]
if min(dp[-1]) != float("inf"):
return min(dp[-1])
# If dp[-1] is inf then the
# partition is not possible
else:
return -1
# Driver Code
if __name__ == "__main__":
# Given array
arr = [ 6, 3, 8, 1, 3, 1, 2, 2 ]
K = 4
# Function call
print(MinimizeSum(arr, K))
C#
using System;
using System.Collections.Generic;
using System.Linq;
public class GFG {
// Function to minimize the sum of
// difference between maximums and
// minimums of K subsets of an array
public static int MinimizeSum(List<int> nums, int k)
{
// Stores count of elements
// in an array
int n = nums.Count;
if (k == n) {
return 0;
}
// Initialize DP[][] array
int inf = 1_000_000_000;
int[][] dp = new int[1 << n][];
for (int i = 0; i < dp.Length; i++) {
dp[i] = new int[n];
for (int j = 0; j < n; j++) {
dp[i][j] = inf;
}
}
// Sort the array
nums.Sort();
// Mark i-th element as not selected
for (int i = 0; i < n; i++) {
dp[1 << i][i] = 0;
}
// Iterate over all possible
// values of mask
for (int mask = 0; mask < (1 << n); mask++) {
// Store count of set bits
// in mask
List<int> n_z_bits = new List<int>();
// Store index of element which is
// already selected in a subset
for (int i = 0; i < n; i++) {
if ((mask >> i & 1) == 1) {
n_z_bits.Add(i);
}
}
// If count of set bits in mask mod (n // k)
// equal
// to 1
if (n_z_bits.Count % (n / k) == 1) {
for (int i = 0; i < n_z_bits.Count; i++) {
for (int j = i + 1; j < n_z_bits.Count;
j++) {
int temp
= dp[mask ^ (1 << n_z_bits[j])]
[n_z_bits[i]];
dp[mask][n_z_bits[j]] = Math.Min(
dp[mask][n_z_bits[j]], temp);
}
}
}
else {
for (int i = 0; i < n_z_bits.Count; i++) {
for (int j = i + 1; j < n_z_bits.Count;
j++) {
if (nums[n_z_bits[i]]
!= nums[n_z_bits[j]]) {
int maskT
= mask ^ (1 << n_z_bits[j]);
int temp
= (dp[maskT][n_z_bits[i]]
+ nums[n_z_bits[i]]
- nums[n_z_bits[j]]);
dp[mask][n_z_bits[j]]
= Math.Min(
dp[mask][n_z_bits[j]],
temp);
}
}
}
}
}
// Return minimum element
// from dp[(1 << N) - 1]
int minVal = inf;
for (int i = 0; i < n; i++) {
minVal = Math.Min(minVal, dp[(1 << n) - 1][i]);
}
// If dp[-1] is inf then the
// partition is not possible
if (minVal == inf) {
return -1;
}
else {
return 999999999 - minVal;
}
}
// Driver Code
static void Main(string[] args)
{
// Given array
List<int> arr
= new List<int>{ 6, 3, 8, 1, 3, 1, 2, 2 };
int k = 4;
Console.WriteLine(MinimizeSum(arr, k));
}
// This code is contributed by Aditya Sharma.
}
JavaScript
// Javascript equivalent
// Function to minimize the sum of
// difference between maximums and
// minimums of K subsets of an array
function MinimizeSum(nums, k) {
// Stores count of elements
// in an array
let n = nums.length;
//Base Case
if (k == n) {
return 0;
}
// Initialize DP[][] array
let inf = 1000000000;
let dp = new Array(1 << n);
for (let i = 0; i < dp.length; i++) {
dp[i] = Array(n).fill(inf);
}
// Sort the array
nums.sort((a, b) => a - b);
// Mark i-th element as not selected
for (let i = 0; i < n; i++) {
dp[1 << i][i] = 0;
}
// Iterate over all possible
// values of mask
for (let mask = 0; mask < (1 << n); mask++) {
// Store count of set bits
// in mask
let n_z_bits = [];
// Store index of element which is
// already selected in a subset
for (let i = 0; i < n; i++) {
if ((mask >> i & 1) == 1) {
n_z_bits.push(i);
}
}
// If count of set bits in mask mod (n // k) equal
// to 1
if (n_z_bits.length % (n / k) == 1) {
for (let i = 0; i < n_z_bits.length; i++) {
for (let j = i + 1; j < n_z_bits.length; j++) {
let temp =
dp[mask ^ (1 << n_z_bits[j])][n_z_bits[i]];
dp[mask][n_z_bits[j]] = Math.min(
dp[mask][n_z_bits[j]],
temp
);
}
}
} else {
for (let i = 0; i < n_z_bits.length; i++) {
for (let j = i + 1; j < n_z_bits.length; j++) {
if (nums[n_z_bits[i]] != nums[n_z_bits[j]]) {
// Check if l-th element
// is already selected or not
let maskT = mask ^ (1 << n_z_bits[j]);
let temp =
dp[maskT][n_z_bits[i]] +
nums[n_z_bits[i]] -
nums[n_z_bits[j]];
// Update dp[mask][l]
dp[mask][n_z_bits[j]] = Math.min(
dp[mask][n_z_bits[j]],
temp
);
}
}
}
}
}
// Return minimum element
// from dp[(1 << N) - 1]
let minVal = inf;
// If dp[-1] is inf then the
// partition is not possible
for (let i = 0; i < n; i++) {
minVal = Math.min(minVal, dp[(1 << n) - 1][i]);
}
if (minVal == inf) {
return -1;
} else {
return 999999999 - minVal;
}
}
let arr = [6,3,8,1,3,1,2,2];
let k = 4;
console.log(MinimizeSum(arr,k));
Time Complexity: O(N^2 * 2N)
Auxiliary Space: O(N^2 * 2N)
/* Complexity Analysis corrected by RainX */
Similar Reads
Minimize count of Subsets with difference between maximum and minimum element not exceeding K
Given an array arr[ ] and an integer K, the task is to split the given array into minimum number of subsets having the difference between the maximum and the minimum element ⤠K. Examples: Input: arr[ ] = {1, 3, 7, 9, 10}, K = 3Output: 2Explanation:One of the possible subsets of arr[] are {1, 3} and
5 min read
Minimize the difference between minimum and maximum elements
Given an array of N integers and an integer k . It is allowed to modify an element either by increasing or decreasing them by k (only once).The task is to minimize and print the maximum difference between the shortest and longest towers.Examples: Input: arr[] = {1, 10, 8, 5}, k = 2Output : Max heigh
8 min read
Minimize difference between maximum and minimum element of all possible subarrays
Given an array arr[ ] of size N, the task is to find the minimum difference between maximum and minimum elements of all possible sized subarrays of arr[ ]. Examples: Input: arr[] = { 5, 14, 7, 10 } Output: 3Explanation: {7, 10} is the subarray having max element = 10 & min element = 7, and their
5 min read
Min difference between maximum and minimum element in all Y size subarrays
Given an array arr[] of size N and integer Y, the task is to find a minimum of all the differences between the maximum and minimum elements in all the sub-arrays of size Y. Examples: Input: arr[] = { 3, 2, 4, 5, 6, 1, 9 } Y = 3Output: 2Explanation:All subarrays of length = 3 are:{3, 2, 4} where maxi
15+ min read
Maximum subset sum having difference between its maximum and minimum in range [L, R]
Given an array arr[] of N positive integers and a range [L, R], the task is to find the maximum subset-sum such that the difference between the maximum and minimum elements of the subset lies in the given range. Examples: Input: arr[] = {6, 5, 0, 9, 1}, L = 0, R = 3Output: 15Explanation: The subset
9 min read
Minimize difference between maximum and minimum array elements by exactly K removals
Given an array arr[] consisting of N positive integers and an integer K, the task is to minimize the difference between the maximum and minimum element in the given array after removing exactly K elements. Examples: Input: arr[] = {5, 1, 6, 7, 12, 10}, K = 3Output: 2Explanation:Remove elements 12, 1
6 min read
Minimum difference between max and min of all K-size subsets
Given an array of integer values, we need to find the minimum difference between the maximum and minimum of all possible K-length subsets. Examples : Input : arr[] = [3, 5, 100, 101, 102] K = 3 Output : 2 Explanation : Possible subsets of K-length with their differences are, [3 5 100] max min diff i
7 min read
Split array into minimum number of subsets having difference between maximum and minimum element at most K
Given an array arr[] consisting of N integers and an integer K, the task is to find the minimum number of sets, the array elements can be divided into such that the difference between the maximum and minimum element of each set is at most K. Examples: Input: arr[] = {1, 2, 3, 4, 5}, K = 2 Output: 2E
6 min read
Minimize difference between maximum and minimum array elements by removing a K-length subarray
Given an array arr[] consisting of N integers and an integer K, the task is to find the minimum difference between the maximum and minimum element present in the array after removing any subarray of size K. Examples: Input: arr[] = {4, 5, 8, 9, 1, 2}, K = 2Output: 4Explanation: Remove the subarray {
10 min read
Split a given array into K subarrays minimizing the difference between their maximum and minimum
Given a sorted array arr[] of N integers and an integer K, the task is to split the array into K subarrays such that the sum of the difference of maximum and minimum element of each subarray is minimized. Examples: Input: arr[] = {1, 3, 3, 7}, K = 4 Output: 0 Explanation: The given array can be spli
6 min read