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

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``            ``// selected 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``// incompatibility 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;` `    ``// Traverse 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));` `    ``// Initialize 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``    ``// incompatibility 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``;` `        ``// Traverse 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];` `        ``// Initialize 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``                ``// selected 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));``    ``}``}`

Python3

 `# Python program for the above approach:` `k ``=` `0``n ``=` `0``goal ``=` `0``dp ``=` `[]``bits ``=` `[]` `def` `__builtin_popcount(n):``    ``count ``=` `0``    ``while` `(n > ``0``): ``        ``count ``+``=` `(n & ``1``)``        ``n >>``=` `1``    ``return` `count` `## Recursive function to find``## the minimum required value``def` `dfs(A, state, index):` `    ``global` `k``    ``global` `n``    ``global` `goal``    ``global` `dp``    ``global` `bits``    ``## Base Case``    ``if` `(index >``=` `k):``        ``return` `0``;` `    ``## Stores the minimum value``    ``## of the current state``    ``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` `bit ``in` `bits:` `        ``## If count of set bit is N/K``        ``if` `(__builtin_popcount(bit) ``=``=` `goal):` `            ``## Store the new state after``            ``## choosing N/K elements``            ``newstate ``=` `state;` `            ``## Stores the minimum and``            ``## maximum of current subset``            ``mn ``=` `100``            ``mx ``=` `-``1` `            ``## Stores if the elements``            ``## have been already``            ``## selected or not``            ``visit ``=` `[``False``]``*``(n``+``1``)` `            ``## Stores if it is possible``            ``## to select N/K elements``            ``good ``=` `True` `            ``## Traverse over the array``            ``for` `j ``in` `range``(``0``, n):` `                ``## 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` `or` `(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``## incompatibility sum``def` `minimumIncompatibility(A, K):` `    ``global` `k``    ``global` `n``    ``global` `goal``    ``global` `dp``    ``global` `bits``    ``n ``=` `len``(A)``    ``k ``=` `K``    ``goal ``=` `n ``/``/` `k` `    ``## Stores the count of element``    ``mp ``=` `{}` `    ``## Traverse the array``    ``for` `i ``in` `A:` `        ``## If number i not occurs``        ``## in Map``        ``if` `(i ``not` `in` `mp):``            ``## Put the element``            ``## in the Map``            ``mp[i] ``=` `0` `        ``## Increment the count of``        ``## i in the Hash Map``        ``mp[i]``+``=``1` `        ``## If count of i in Map is``        ``## greater than K then``        ``## return -1``        ``if` `(mp[i] > k):``            ``return` `-``1``;` `    ``## Stores all total state``    ``state ``=` `(``1` `<< n) ``-` `1``;` `    ``## Traverse over all the state``    ``for` `i ``in` `range``(state ``+` `1``):` `        ``## If number of set bit``        ``## is equal to N/K``        ``if` `(__builtin_popcount(i) ``=``=` `goal):``            ``bits.append(i)` `    ``## Stores the minimum value``    ``## at a state``    ``for` `i ``in` `range``(``1` `<< n):``        ``dp.append([])``        ``for` `j ``in` `range``(k):``            ``dp[i].append(``-``1``)` `    ``## Call the recursive function``    ``return` `dfs(A, state, ``0``);` `## Driver code``if` `__name__``=``=``'__main__'``:` `    ``arr ``=` `[ ``1``, ``2``, ``1``, ``4` `]``    ``K ``=` `2` `    ``## Function Call``    ``print``(minimumIncompatibility(arr, K))` `    ``# This code is contributed by subhamgoyal2014.`

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``  ``// incompatibility 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;` `    ``// Traverse 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];` `    ``// Initialize 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``        ``// selected 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)

Previous
Next