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.
- 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)
Last Updated :
15 Jun, 2022
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...