Related Articles
Minimize sum of incompatibilities of K equal-length subsets made up of unique elements
• Difficulty Level : Expert
• Last Updated : 09 Mar, 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.`

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 mathematical concepts for competitive programming with the Essential Maths for CP Course at a student-friendly price. To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

My Personal Notes arrow_drop_up