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 [Tex]N [/Tex]integers and an integer [Tex]k [/Tex]. 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},
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