Given an array arr[] of size N and an integer K, the task is to minimize the sum of 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 6Input: 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:
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)) |
6
Time Complexity: O(N* 2N)
Auxiliary Space: O(N * 2N)
Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.