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.
- Check if dp[mask][i] != -1, then return dp[mask][i] as the current state is already calculated.
- 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:
dp[mask][i] = min(dp[mask][i], Y – X + dfs(newmask, i))
- 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++
#include <bits/stdc++.h>
using namespace std;
int k;
int n;
int goal;
vector<vector< int >> dp;
vector< int > bits;
int dfs(vector< int > A, int state, int index)
{
if (index >= k)
{
return 0;
}
int res = 1000;
if (dp[state][index] != -1) {
return dp[state][index];
}
for ( int bit : bits) {
if (__builtin_popcount(bit)
== goal) {
int newstate = state;
int mn = 100, mx = -1;
vector< bool > visit(n+1, false );
bool good = true ;
for ( int j = 0; j < n; j++) {
if ((bit & (1 << j)) != 0) {
if (visit[A[j]] == true
|| (state & (1 << j)) == 0) {
good = false ;
break ;
}
visit[A[j]] = true ;
newstate = newstate
^ (1 << j);
mx = max(mx,
A[j]);
mn = min(mn,
A[j]);
}
}
if (good) {
res = min(
res, mx - mn
+ dfs(A, newstate,
index + 1));
}
}
}
dp[state][index] = res;
return res;
}
int minimumIncompatibility(vector< int > A, int K)
{
n = A.size();
k = K;
goal = n / k;
map< int , int > mp;
for ( int i : A) {
if (mp.find(i)==mp.end()){
mp[i] = 0;
}
mp[i]++;
if (mp[i] > k)
return -1;
}
int state = (1 << n) - 1;
for ( int i = 0; i <= state; i++) {
if (__builtin_popcount(i) == goal){
bits.push_back(i);
}
}
dp.resize(1<<n,vector< int >(k,-1));
return dfs(A, state, 0);
}
int main()
{
vector< int > arr = { 1, 2, 1, 4 };
int K = 2;
cout<<(minimumIncompatibility(arr, K));
}
|
Java
import java.io.*;
import java.util.*;
class Solution {
int k;
int n;
int goal;
int dp[][];
List<Integer> bits = new ArrayList<>();
public int minimumIncompatibility(
int [] A, int k)
{
this .n = A.length;
this .k = k;
goal = n / k;
Map<Integer, Integer> map
= new HashMap<>();
for ( int i : A) {
if (!map.containsKey(i))
map.put(i, 0 );
map.put(i, map.get(i) + 1 );
if (map.get(i) > k)
return - 1 ;
}
int state = ( 1 << n) - 1 ;
for ( int i = 0 ; i <= state; i++) {
if (Integer.bitCount(i) == goal)
bits.add(i);
}
dp = new int [ 1 << n][k];
for ( int i = 0 ;
i < dp.length; i++) {
Arrays.fill(dp[i], - 1 );
}
return dfs(A, state, 0 );
}
public int dfs( int A[], int state,
int index)
{
if (index >= k) {
return 0 ;
}
int res = 1000 ;
if (dp[state][index] != - 1 ) {
return dp[state][index];
}
for ( int bit : bits) {
if (Integer.bitCount(bit)
== goal) {
int newstate = state;
int mn = 100 , mx = - 1 ;
boolean visit[]
= new boolean [n + 1 ];
boolean good = true ;
for ( int j = 0 ; j < n; j++) {
if ((bit & ( 1 << j)) != 0 ) {
if (visit[A[j]] == true
|| (state & ( 1 << j)) == 0 ) {
good = false ;
break ;
}
visit[A[j]] = true ;
newstate = newstate
^ ( 1 << j);
mx = Math.max(mx,
A[j]);
mn = Math.min(mn,
A[j]);
}
}
if (good) {
res = Math.min(
res, mx - mn
+ dfs(A, newstate,
index + 1 ));
}
}
}
dp[state][index] = res;
return res;
}
}
class GFG {
public static void main(String[] args)
{
Solution st = new Solution();
int [] arr = { 1 , 2 , 1 , 4 };
int K = 2 ;
System.out.print(
st.minimumIncompatibility(arr, K));
}
}
|
Python3
k = 0
n = 0
goal = 0
dp = []
bits = []
def __builtin_popcount(n):
count = 0
while (n > 0 ):
count + = (n & 1 )
n >> = 1
return count
def dfs(A, state, index):
global k
global n
global goal
global dp
global bits
if (index > = k):
return 0 ;
res = 1000
if (dp[state][index] ! = - 1 ):
return dp[state][index];
for bit in bits:
if (__builtin_popcount(bit) = = goal):
newstate = state;
mn = 100
mx = - 1
visit = [ False ] * (n + 1 )
good = True
for j in range ( 0 , n):
if ((bit & ( 1 << j)) ! = 0 ):
if (visit[A[j]] = = True or (state & ( 1 << j)) = = 0 ):
good = False ;
break ;
visit[A[j]] = True ;
newstate = newstate ^ ( 1 << j);
mx = max (mx, A[j])
mn = min (mn, A[j])
if (good):
res = min (res, mx - mn + dfs(A, newstate, index + 1 ))
dp[state][index] = res
return res
def minimumIncompatibility(A, K):
global k
global n
global goal
global dp
global bits
n = len (A)
k = K
goal = n / / k
mp = {}
for i in A:
if (i not in mp):
mp[i] = 0
mp[i] + = 1
if (mp[i] > k):
return - 1 ;
state = ( 1 << n) - 1 ;
for i in range (state + 1 ):
if (__builtin_popcount(i) = = goal):
bits.append(i)
for i in range ( 1 << n):
dp.append([])
for j in range (k):
dp[i].append( - 1 )
return dfs(A, state, 0 );
if __name__ = = '__main__' :
arr = [ 1 , 2 , 1 , 4 ]
K = 2
print (minimumIncompatibility(arr, K))
|
C#
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 >();
public int minimumIncompatibility(
int [] A, int k)
{
this .n = A.Length;
this .k = k;
goal = n / k;
Dictionary< int , int > map
= new Dictionary< int , int >();
foreach ( int i in A) {
if (!map.ContainsKey(i))
map[i]= 0;
map[i]++;
if (map[i] > k)
return -1;
}
int state = (1 << n) - 1;
for ( int i = 0; i <= state; i++) {
if (Convert.ToString(i, 2).Count(c => c == '1' ) == goal)
bits.Add(i);
}
dp = new int [1 << n,k];
for ( int i = 0;i < dp.GetLength(0); i++) {
for ( int j = 0;j < dp.GetLength(1); j++) {
dp[i,j]=-1;
}
}
return dfs(A, state, 0);
}
public int dfs( int []A, int state,
int index)
{
if (index >= k) {
return 0;
}
int res = 1000;
if (dp[state,index] != -1) {
return dp[state,index];
}
foreach ( int bit in bits) {
if (Convert.ToString(bit, 2).Count(c => c == '1' )== goal) {
int newstate = state;
int mn = 100, mx = -1;
bool []visit
= new bool [n + 1];
bool good = true ;
for ( int j = 0; j < n; j++) {
if ((bit & (1 << j)) != 0) {
if (visit[A[j]] == true
|| (state & (1 << j)) == 0) {
good = false ;
break ;
}
visit[A[j]] = true ;
newstate = newstate
^ (1 << j);
mx = Math.Max(mx,
A[j]);
mn = Math.Min(mn,
A[j]);
}
}
if (good) {
res = Math.Min(
res, mx - mn
+ dfs(A, newstate,
index + 1));
}
}
}
dp[state,index] = res;
return res;
}
}
class GFG {
public static void Main()
{
Solution st = new Solution();
int [] arr = { 1, 2, 1, 4 };
int K = 2;
Console.Write(
st.minimumIncompatibility(arr, K));
}
}
|
Javascript
<script>
let k,n,goal;
let dp;
let bits = [];
function minimumIncompatibility(A,K)
{
n = A.length;
k = K;
goal = Math.floor(n / k);
let map = new Map();
for (let i=0;i< A.length;i++) {
if (!map.has(A[i]))
map.set(A[i], 0);
map.set(A[i], map.get(A[i]) + 1);
if (map.get(A[i]) > k)
return -1;
}
let state = (1 << n) - 1;
for (let i = 0; i <= state; i++) {
if (i.toString(2).split( '0' ).join( '' ).length == goal)
bits.push(i);
}
dp = new Array(1 << n);
for (let i = 0;
i < dp.length; i++) {
dp[i]= new Array(k);
for (let j=0;j<k;j++)
dp[i][j]=-1;
}
return dfs(A, state, 0);
}
function dfs(A,state,index)
{
if (index >= k) {
return 0;
}
let res = 1000;
if (dp[state][index] != -1) {
return dp[state][index];
}
for (let bit=0;bit< bits.length;bit++) {
if (bits[bit].toString(2).split( '0' ).join( '' ).length
== goal) {
let newstate = state;
let mn = 100, mx = -1;
let visit
= new Array(n + 1);
for (let i=0;i<=n;i++)
{
visit[i]= false ;
}
let good = true ;
for (let j = 0; j < n; j++) {
if ((bits[bit] & (1 << j)) != 0) {
if (visit[A[j]] == true
|| (state & (1 << j)) == 0) {
good = false ;
break ;
}
visit[A[j]] = true ;
newstate = newstate
^ (1 << j);
mx = Math.max(mx,
A[j]);
mn = Math.min(mn,
A[j]);
}
}
if (good) {
res = Math.min(
res, mx - mn
+ dfs(A, newstate,
index + 1));
}
}
}
dp[state][index] = res;
return res;
}
let arr=[1, 2, 1, 4];
let K = 2;
document.write(minimumIncompatibility(arr, K))
</script>
|
Time Complexity: O(N2*22*N)
Auxiliary Space: O(N)
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
15 Jun, 2022
Like Article
Save Article