Related Articles

# Minimize sum of incompatibilities of K equal-length subsets made up of unique elements

• Difficulty Level : Expert
• Last Updated : 30 Jun, 2021

Given an array arr[] consisting of N integers and an integer K, the task is to find the minimum sum of incompatibilities of K subsets of equal sizes having unique elements.

The difference between the maximum and the minimum element in a set is known as the incompatibility of a set.

Examples:

Input: arr[] = {1, 2, 1, 4}, K = 2
Output: 4
Explanation:
One of the possible ways of distributing the array into K(i.e., 2) subsets is {1, 2} and {1, 4}.
The incompatibility of the first subset = (2 – 1) = 1.
The incompatibility of the second subset = (4 – 1) = 3.
Therefore, the total sum of incompatibilities of both subsets = 1 + 3 = 4, which is the minimum among all possibilities.

Input: arr[] = {6, 3, 8, 1, 3, 1, 2, 2}, K = 4
Output: 6
Explanation:
One of the possible ways of distributing the array into K subset is: {1, 2}, {2, 3}, {6, 8}, {1, 3}.
The incompatibility of the first subset = (2-1) = 1.
The incompatibility of the second subset = (3-2) = 1.
The incompatibility of the third subset = (8-6) = 2.
The incompatibility of the fourth subset = (3-1) = 2.
Therefore, total sum of incompatibilities of K subset = 1 + 1 + 2 + 2 = 6. And it is also the minimum among all possibilities

Naive Approach: The simplest approach is to traverse the given array recursively and in each recursion traverse over all possible ways of selecting N/K elements of the array using bitmask and calculate the incompatibility of that subset and then return the minimum among all.

Time Complexity: O(N*23*N)
Auxiliary Space: O(N)

Efficient Approach: The above approach can be optimized using dynamic programming. The given problem can be solved based on the following observations:

• It can be observed that it requires a 2 state Dynamic programming with Bitmasking say DP(mask, i) to solve the problem where i represents the current position of the array and each binary bit of mask represent if the element has been already selected or not.
• The transition state will include calculating the incompatibility by selecting a subset of size N/K.
• Suppose X and Y is minimum and maximum of current set and newmask is another variable with value initially as the mask
• Now, mark all the N/K elements that have been selected occurs only once in newmask then DP(mask, i) is calculated by (Y – X + min(DP(newmask, i + 1), DP(mask, i))).

Follow the steps below to solve the problem:

• Initialize a 2D array, say dp[][].
• Define a recursive function, say dfs (mask, i), to calculate the result:
• Base Case: If i > K, then return 0.
• Select N/K elements from the array using bitmasking and if it possible to choose i elements of the subset which only occurs once and are not already part of other subsets, then update the current dp state as:

• Return the value of dp[mask][i] as the result in the current recursive call.
• Call the recursive function dfs(2N-1, 0) and print the value returned by it.

Below is the implementation of the above approach:

## C++

 `// C++ program for the above approach``#include ``using` `namespace` `std;``int` `k;``int` `n;``int` `goal;``vector> dp;``vector<``int``> bits;` `// Recursive function to find``// the minimum required value``int` `dfs(vector<``int``> A, ``int` `state,``int` `index)``{``  ` `    ``// Base Case``    ``if` `(index >= k)``    ``{``        ``return` `0;``    ``}` `    ``// Stores the minimum value``    ``// of the current state``    ``int` `res = 1000;` `    ``// If dp[state][index] is``    ``// already calculated``    ``if` `(dp[state][index] != -1) {` `        ``// return dp[state][index]``        ``return` `dp[state][index];``    ``}` `    ``// Traverse over all the bits``    ``for` `(``int` `bit : bits) {` `        ``// If count of set bit is N/K``        ``if` `(__builtin_popcount(bit)``            ``== goal) {` `            ``// Store the new state after``            ``// choosing N/K elements``            ``int` `newstate = state;` `            ``// Stores the minimum and``            ``// maximum of current subset``            ``int` `mn = 100, mx = -1;` `            ``// Stores if the elements``            ``// have been already``            ``// selsected or not``            ``vector<``bool``> visit(n+1,``false``);` `            ``// Stores if it is possible``            ``// to select N/K elements``            ``bool` `good = ``true``;` `            ``// Traverse over the array``            ``for` `(``int` `j = 0; j < n; j++) {` `                ``// If not chosen already``                ``// for another subset``                ``if` `((bit & (1 << j)) != 0) {` `                    ``// If already chosen``                    ``// for another subset``                    ``// or current subset``                    ``if` `(visit[A[j]] == ``true``                        ``|| (state & (1 << j)) == 0) {` `                        ``// Mark the good false``                        ``good = ``false``;``                        ``break``;``                    ``}` `                    ``// Mark the current``                    ``// number visited``                    ``visit[A[j]] = ``true``;` `                    ``// Mark the current``                    ``// position in mask``                    ``// newstate``                    ``newstate = newstate``                               ``^ (1 << j);` `                    ``// Update the maximum``                    ``// and minimum``                    ``mx = max(mx,``                                  ``A[j]);``                    ``mn = min(mn,``                                  ``A[j]);``                ``}``            ``}` `            ``// If good is true then``            ``// Update the res``            ``if` `(good) {``                ``res = min(``                    ``res, mx - mn``                             ``+ dfs(A, newstate,``                                   ``index + 1));``            ``}``        ``}``    ``}` `    ``// Update the current sp state``    ``dp[state][index] = res;` `    ``// Return the res``    ``return` `res;``}` `// Function to find the minimum``// incomatibility sum``int` `minimumIncompatibility(vector<``int``> A, ``int` `K)``{``    ``n = A.size();``    ``k = K;``    ``goal = n / k;` `    ``// Stores the count of element``    ``map<``int``, ``int``> mp;` `    ``// Traverse the array``    ``for` `(``int` `i : A) {` `        ``// If number i not occurs``        ``// in Map``        ``if` `(mp.find(i)!=mp.end()){``            ``// Put the element``            ``// in the Map``            ``mp[i] = 0;``          ``}` `        ``// Increment the count of``        ``// i in the Hash Map``        ``mp[i]++;` `        ``// If count of i in Map is``        ``// greater than K then``        ``// return -1``        ``if` `(mp[i] > k)``            ``return` `-1;``    ``}` `    ``// Stores all total state``    ``int` `state = (1 << n) - 1;` `    ``// Travere over all the state``    ``for` `(``int` `i = 0; i <= state; i++) {` `        ``// If number of set bit``        ``// is equal to N/K``        ``if` `(__builtin_popcount(i) == goal)``            ``bits.push_back(i);``    ``}` `    ``// Stores the minimum value``    ``// at a state``    ``dp.resize(1<(k,-1));` `    ``// Intiallize the dp state``    ``// with -1``    ``// for (int i = 0;``    ``//      i < dp.ize(); i++) {``    ``//     Arrays.fill(dp[i], -1);``    ``// }` `    ``// Call the recursive function``    ``return` `dfs(A, state, 0);``}` `// Driver code``int` `main()``{` `    ``vector<``int``> arr = { 1, 2, 1, 4 };``    ``int` `K = 2;` `    ``// Function Call``    ``cout<<(minimumIncompatibility(arr, K));``}` `// This code is contributed by mohit kumar 29.`

## Java

 `// Java program for the above approach``import` `java.io.*;``import` `java.util.*;` `class` `Solution {``    ``int` `k;``    ``int` `n;``    ``int` `goal;``    ``int` `dp[][];``    ``List bits = ``new` `ArrayList<>();` `    ``// Function to find the minimum``    ``// incomatibility sum``    ``public` `int` `minimumIncompatibility(``        ``int``[] A, ``int` `k)``    ``{``        ``this``.n = A.length;``        ``this``.k = k;``        ``goal = n / k;` `        ``// Stores the count of element``        ``Map map``            ``= ``new` `HashMap<>();` `        ``// Traverse the array``        ``for` `(``int` `i : A) {` `            ``// If number i not occurs``            ``// in Map``            ``if` `(!map.containsKey(i))` `                ``// Put the element``                ``// in the Map``                ``map.put(i, ``0``);` `            ``// Increment the count of``            ``// i in the Hash Map``            ``map.put(i, map.get(i) + ``1``);` `            ``// If count of i in Map is``            ``// greater than K then``            ``// return -1``            ``if` `(map.get(i) > k)``                ``return` `-``1``;``        ``}` `        ``// Stores all total state``        ``int` `state = (``1` `<< n) - ``1``;` `        ``// Travere over all the state``        ``for` `(``int` `i = ``0``; i <= state; i++) {` `            ``// If number of set bit``            ``// is equal to N/K``            ``if` `(Integer.bitCount(i) == goal)``                ``bits.add(i);``        ``}` `        ``// Stores the minimum value``        ``// at a state``        ``dp = ``new` `int``[``1` `<< n][k];` `        ``// Intiallize the dp state``        ``// with -1``        ``for` `(``int` `i = ``0``;``             ``i < dp.length; i++) {``            ``Arrays.fill(dp[i], -``1``);``        ``}` `        ``// Call the recursive function``        ``return` `dfs(A, state, ``0``);``    ``}` `    ``// Recursive function to find``    ``// the minimum required value``    ``public` `int` `dfs(``int` `A[], ``int` `state,``                   ``int` `index)``    ``{``        ``// Base Case``        ``if` `(index >= k) {``            ``return` `0``;``        ``}` `        ``// Stores the minimum value``        ``// of the current state``        ``int` `res = ``1000``;` `        ``// If dp[state][index] is``        ``// already calculated``        ``if` `(dp[state][index] != -``1``) {` `            ``// return dp[state][index]``            ``return` `dp[state][index];``        ``}` `        ``// Traverse over all the bits``        ``for` `(``int` `bit : bits) {` `            ``// If count of set bit is N/K``            ``if` `(Integer.bitCount(bit)``                ``== goal) {` `                ``// Store the new state after``                ``// choosing N/K elements``                ``int` `newstate = state;` `                ``// Stores the minimum and``                ``// maximum of current subset``                ``int` `mn = ``100``, mx = -``1``;` `                ``// Stores if the elements``                ``// have been already``                ``// selsected or not``                ``boolean` `visit[]``                    ``= ``new` `boolean``[n + ``1``];` `                ``// Stores if it is possible``                ``// to select N/K elements``                ``boolean` `good = ``true``;` `                ``// Traverse over the array``                ``for` `(``int` `j = ``0``; j < n; j++) {` `                    ``// If not chosen already``                    ``// for another subset``                    ``if` `((bit & (``1` `<< j)) != ``0``) {` `                        ``// If already chosen``                        ``// for another subset``                        ``// or current subset``                        ``if` `(visit[A[j]] == ``true``                            ``|| (state & (``1` `<< j)) == ``0``) {` `                            ``// Mark the good false``                            ``good = ``false``;``                            ``break``;``                        ``}` `                        ``// Mark the current``                        ``// number visited``                        ``visit[A[j]] = ``true``;` `                        ``// Mark the current``                        ``// position in mask``                        ``// newstate``                        ``newstate = newstate``                                   ``^ (``1` `<< j);` `                        ``// Update the maximum``                        ``// and minimum``                        ``mx = Math.max(mx,``                                      ``A[j]);``                        ``mn = Math.min(mn,``                                      ``A[j]);``                    ``}``                ``}` `                ``// If good is true then``                ``// Update the res``                ``if` `(good) {``                    ``res = Math.min(``                        ``res, mx - mn``                                 ``+ dfs(A, newstate,``                                       ``index + ``1``));``                ``}``            ``}``        ``}` `        ``// Update the current sp state``        ``dp[state][index] = res;` `        ``// Return the res``        ``return` `res;``    ``}``}` `// Driver Code``class` `GFG {` `    ``public` `static` `void` `main(String[] args)``    ``{``        ``Solution st = ``new` `Solution();``        ``int``[] arr = { ``1``, ``2``, ``1``, ``4` `};``        ``int` `K = ``2``;` `        ``// Function Call``        ``System.out.print(``            ``st.minimumIncompatibility(arr, K));``    ``}``}`

## C#

 `// C# program for the above approach``using` `System;``using` `System.Collections;``using` `System.Collections.Generic;``using` `System.Linq;` `class` `Solution {``  ``int` `k;``  ``int` `n;``  ``int` `goal;``  ``int` `[,]dp;``  ``List<``int``> bits = ``new` `List<``int``>();` `  ``// Function to find the minimum``  ``// incomatibility sum``  ``public` `int` `minimumIncompatibility(``    ``int``[] A, ``int` `k)``  ``{``    ``this``.n = A.Length;``    ``this``.k = k;``    ``goal = n / k;` `    ``// Stores the count of element``    ``Dictionary<``int``,``int``> map``      ``= ``new` `Dictionary<``int``,``int``>();` `    ``// Traverse the array``    ``foreach``(``int` `i ``in` `A) {` `      ``// If number i not occurs``      ``// in Map``      ``if` `(!map.ContainsKey(i))` `        ``// Put the element``        ``// in the Map``        ``map[i]= 0;` `      ``// Increment the count of``      ``// i in the Hash Map``      ``map[i]++;` `      ``// If count of i in Map is``      ``// greater than K then``      ``// return -1``      ``if` `(map[i] > k)``        ``return` `-1;``    ``}` `    ``// Stores all total state``    ``int` `state = (1 << n) - 1;` `    ``// Travere over all the state``    ``for` `(``int` `i = 0; i <= state; i++) {` `      ``// If number of set bit``      ``// is equal to N/K``      ``if` `(Convert.ToString(i, 2).Count(c => c == ``'1'``) == goal)``        ``bits.Add(i);``    ``}` `    ``// Stores the minimum value``    ``// at a state``    ``dp = ``new` `int``[1 << n,k];` `    ``// Intiallize the dp state``    ``// with -1``    ``for` `(``int` `i = 0;i < dp.GetLength(0); i++) {` `      ``for` `(``int` `j = 0;j < dp.GetLength(1); j++) {``        ``dp[i,j]=-1;``      ``}` `    ``}` `    ``// Call the recursive function``    ``return` `dfs(A, state, 0);``  ``}` `  ``// Recursive function to find``  ``// the minimum required value``  ``public` `int` `dfs(``int` `[]A, ``int` `state,``                 ``int` `index)``  ``{``    ``// Base Case``    ``if` `(index >= k) {``      ``return` `0;``    ``}` `    ``// Stores the minimum value``    ``// of the current state``    ``int` `res = 1000;` `    ``// If dp[state][index] is``    ``// already calculated``    ``if` `(dp[state,index] != -1) {` `      ``// return dp[state][index]``      ``return` `dp[state,index];``    ``}` `    ``// Traverse over all the bits``    ``foreach``(``int` `bit ``in` `bits) {` `      ``// If count of set bit is N/K``      ``if``(Convert.ToString(bit, 2).Count(c => c == ``'1'``)== goal) {` `        ``// Store the new state after``        ``// choosing N/K elements``        ``int` `newstate = state;` `        ``// Stores the minimum and``        ``// maximum of current subset``        ``int` `mn = 100, mx = -1;` `        ``// Stores if the elements``        ``// have been already``        ``// selsected or not``        ``bool` `[]visit``          ``= ``new` `bool``[n + 1];` `        ``// Stores if it is possible``        ``// to select N/K elements``        ``bool` `good = ``true``;` `        ``// Traverse over the array``        ``for` `(``int` `j = 0; j < n; j++) {` `          ``// If not chosen already``          ``// for another subset``          ``if` `((bit & (1 << j)) != 0) {` `            ``// If already chosen``            ``// for another subset``            ``// or current subset``            ``if` `(visit[A[j]] == ``true``                ``|| (state & (1 << j)) == 0) {` `              ``// Mark the good false``              ``good = ``false``;``              ``break``;``            ``}` `            ``// Mark the current``            ``// number visited``            ``visit[A[j]] = ``true``;` `            ``// Mark the current``            ``// position in mask``            ``// newstate``            ``newstate = newstate``              ``^ (1 << j);` `            ``// Update the maximum``            ``// and minimum``            ``mx = Math.Max(mx,``                          ``A[j]);``            ``mn = Math.Min(mn,``                          ``A[j]);``          ``}``        ``}` `        ``// If good is true then``        ``// Update the res``        ``if` `(good) {``          ``res = Math.Min(``            ``res, mx - mn``            ``+ dfs(A, newstate,``                  ``index + 1));``        ``}``      ``}``    ``}` `    ``// Update the current sp state``    ``dp[state,index] = res;` `    ``// Return the res``    ``return` `res;``  ``}``}` `// Driver Code``class` `GFG {` `  ``public` `static` `void` `Main()``  ``{``    ``Solution st = ``new` `Solution();``    ``int``[] arr = { 1, 2, 1, 4 };``    ``int` `K = 2;` `    ``// Function Call``    ``Console.Write(``      ``st.minimumIncompatibility(arr, K));``  ``}``}` `// This code is contributed by rutvik_56.`

## Javascript

 ``
Output:
`4`

Time Complexity: O(N2*22*N)
Auxiliary Space: O(N)

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.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

My Personal Notes arrow_drop_up