Partition of a set into k subsets with equal sum using BitMask and DP
Last Updated :
26 Nov, 2024
Given an integer array arr[] and an integer k, the task is to check if it is possible to divide the given array into k non-empty subsets of equal sum such that every array element is part of a single subset.
Examples:
Input: arr[] = [2, 1, 4, 5, 6], k = 3
Output: true
Explanation: Possible subsets of the given array are [2, 4], [1, 5] and [6]
Input: arr[] = [2, 1, 5, 5, 6], k = 3
Output: false
Explanation: It is not possible to divide above array into 3 parts with equal sum.
Using Recursion - O(k*2^n) Time and O(n) Space
For the recursive approach, refer to partitioning a set into k subsets with equal sum. For each value of k, we use recursion to generate all possible subsequences of the array and check if any of them forms a valid subset with the required sum. Once a valid subset is found, its elements are marked as used, and the recursion continues for the remaining subsets. This process is repeated recursively for all k subsets, exploring all combinations until either the subsets are successfully formed or no further options remain.
Using Bitmasking and DP - O(n*2^n) and O(2^n) Space
The idea is to use mask to determine the current state. The current state will tell us about the subset already formed (which numbers are already selected).
For example: arr[] = [2, 1, 4, 3, 5, 6, 2], mask = (1100101), which means that [2, 1, 5, 2] are already chosen in the current mask.
For any current state mask, the jth element will be added to it based on the following two conditions:
- The jth bit is not set in the mask (mask & (1<<j) == 0)
- sum (mask) + arr[j] <= target ( where target = (sum of array elements) / k)
Maintain a table dp[] such that dp[i] store the sum of elements in mask i. So, the dp transitions will be:
dp[i | (1 << j)] = (dp[i] + arr[j]) % target
C++
// C++ program to check if the
// given array can be partitioned
// into K subsets with equal sum
// using bitmasking dp
#include <bits/stdc++.h>
using namespace std;
bool isKPartitionPossible(vector<int> &arr, int k) {
int n = arr.size();
if (k == 1)
// Return true as the entire array is the answer
return true;
// If total number of partitions exceeds
// size of the array
if (n < k)
return false;
int sum = 0;
for (int i = 0; i < n; i++)
sum += arr[i];
// If the array sum is not divisible by K
if (sum % k != 0)
// No such partitions are possible
return false;
// Required sum of each subset
int target = sum / k;
// Initialize dp vector with -1
vector<int> dp(1 << n, -1);
// Sum of empty subset is zero
dp[0] = 0;
// Iterate over all subsets/masks
for (int mask = 0; mask < (1 << n); mask++) {
// if current mask is invalid, continue
if (dp[mask] == -1)
continue;
// Iterate over all array elements
for (int i = 0; i < n; i++) {
// Check if the current element can be added
// to the current subset/mask
if (!(mask & (1 << i)) && dp[mask] + arr[i] <= target) {
dp[mask | (1 << i)] = (dp[mask] + arr[i]) % target;
}
}
}
// If the dp value of all elements used is zero, then
// partitioning is possible
return dp[(1 << n) - 1] == 0;
}
int main() {
vector<int> arr = {2, 1, 4, 5, 3, 3};
int k = 2;
if (isKPartitionPossible(arr, k)) {
cout << "true";
}
else {
cout << "false";
}
}
Java
// Java program to check if the
// given array can be partitioned
// into K subsets with equal sum
// using bitmasking dp
import java.util.*;
class GfG {
static boolean isKPartitionPossible(int[] arr, int k) {
int n = arr.length;
if (k == 1)
// Return true as the entire array
// is the answer
return true;
// If total number of partitions exceeds size of the
// array
if (n < k)
return false;
int sum = 0;
for (int i = 0; i < n; i++)
sum += arr[i];
// If the array sum is not divisible by K
if (sum % k != 0)
// No such partitions are possible
return false;
// Required sum of each subset
int target = sum / k;
// Initialize dp array with -1
int[] dp = new int[1 << n];
Arrays.fill(dp, -1);
// Sum of empty subset is zero
dp[0] = 0;
// Iterate over all subsets/masks
for (int mask = 0; mask < (1 << n); mask++) {
// if current mask is invalid, continue
if (dp[mask] == -1)
continue;
// Iterate over all array elements
for (int i = 0; i < n; i++) {
// Check if the current element can be added
// to the current subset/mask
if ((mask & (1 << i)) == 0
&& dp[mask] + arr[i] <= target) {
// transition
dp[mask | (1 << i)]
= (dp[mask] + arr[i]) % target;
}
}
}
// If the dp value of all elements used is zero,
// then partitioning is possible
return dp[(1 << n) - 1] == 0;
}
public static void main(String[] args) {
int[] arr = { 2, 1, 4, 5, 3, 3 };
int k = 3;
if (isKPartitionPossible(arr, k)) {
System.out.println("true");
}
else {
System.out.println("false");
}
}
}
Python
# Program program to check if the
# given array can be partitioned
# into K subsets with equal sum
# using bitmasking dp
def isKPartitionPossible(arr, k):
n = len(arr)
if k == 1:
# Return True as the entire array
# is the answer
return True
# If total number of partitions exceeds
# size of the array
if n < k:
return False
totalSum = sum(arr)
# If the array sum is not divisible by K
if totalSum % k != 0:
# No such partitions are possible
return False
# Required sum of each subset
target = totalSum // k
# Initialize dp array with -1
dp = [-1] * (1 << n)
# Sum of empty subset is zero
dp[0] = 0
# Iterate over all subsets/masks
for mask in range(1 << n):
# If the current mask is invalid, continue
if dp[mask] == -1:
continue
# Iterate over all array elements
for i in range(n):
# Check if the current element can be added
# to the current subset/mask
if (mask & (1 << i)) == 0 and dp[mask] + arr[i] <= target:
# Transition
dp[mask | (1 << i)] = (dp[mask] + arr[i]) % target
# If the dp value of all elements used is zero,
# then partitioning is possible
return dp[(1 << n) - 1] == 0
if __name__ == "__main__":
arr = [2, 1, 4, 5, 3, 3]
k = 3
if isKPartitionPossible(arr, k):
print("true")
else:
print("false")
C#
// C# program to check if the
// given array can be partitioned
// into K subsets with equal sum
// using bitmasking dp
using System;
class GfG {
static bool isKPartitionPossible(int[] arr, int k) {
int n = arr.Length;
if (k == 1) {
// Return true as the entire array
// is the answer
return true;
}
// If total number of partitions exceeds
// size of the array
if (n < k) {
return false;
}
int totalSum = 0;
foreach(int num in arr) { totalSum += num; }
// If the array sum is not divisible by k
if (totalSum % k != 0) {
return false;
}
// Required sum of each subset
int target = totalSum / k;
// Initialize dp array with -1
int[] dp = new int[1 << n];
for (int i = 0; i < (1 << n); i++) {
dp[i] = -1;
}
// Sum of empty subset is zero
dp[0] = 0;
// Iterate over all subsets/masks
for (int mask = 0; mask < (1 << n); mask++) {
// If the current mask is invalid, continue
if (dp[mask] == -1)
continue;
// Iterate over all array elements
for (int i = 0; i < n; i++) {
// Check if the current element can be added
// to the current subset/mask
if ((mask & (1 << i)) == 0
&& dp[mask] + arr[i] <= target) {
// Transition
dp[mask | (1 << i)]
= (dp[mask] + arr[i]) % target;
}
}
}
// If the dp value of all elements used is zero,
// then partitioning is possible
return dp[(1 << n) - 1] == 0;
}
static void Main(string[] args) {
int[] arr = { 2, 1, 4, 5, 3, 3 };
int k = 3;
if (isKPartitionPossible(arr, k)) {
Console.WriteLine("true");
}
else {
Console.WriteLine("false");
}
}
}
JavaScript
// JavaScript program to check if the
// given array can be partitioned
// into K subsets with equal sum
// using bitmasking dp
function isKPartitionPossible(arr, k) {
const n = arr.length;
if (k === 1) {
// Return true as the entire
// array is the answer
return true;
}
// If total number of partitions exceeds size of the
// array
if (n < k) {
return false;
}
let totalSum = 0;
for (let num of arr) {
totalSum += num;
}
// If the array sum is not divisible by k
if (totalSum % k !== 0) {
return false;
}
// Required sum of each subset
const target = totalSum / k;
// Initialize dp array with -1
const dp = new Array(1 << n).fill(-1);
// Sum of empty subset is zero
dp[0] = 0;
// Iterate over all subsets/masks
for (let mask = 0; mask < (1 << n); mask++) {
// If the current mask is invalid, continue
if (dp[mask] === -1)
continue;
// Iterate over all array elements
for (let i = 0; i < n; i++) {
// Check if the current element can be added to
// the current subset/mask
if ((mask & (1 << i)) === 0
&& dp[mask] + arr[i] <= target) {
// Transition
dp[mask | (1 << i)]
= (dp[mask] + arr[i]) % target;
}
}
}
// If the dp value of all elements used is zero, then
// partitioning is possible
return dp[(1 << n) - 1] === 0;
}
const arr = [ 2, 1, 4, 5, 3, 3 ];
const k = 3;
if (isKPartitionPossible(arr, k)) {
console.log("true");
}
else {
console.log("false");
}
Similar Reads
Partition of a set into K subsets with equal sum Given an integer array arr[] and an integer k, the task is to check if it is possible to divide the given array into k non-empty subsets of equal sum such that every array element is part of a single subset.Examples: Input: arr[] = [2, 1, 4, 5, 6], k = 3 Output: trueExplanation: Possible subsets of
9 min read
Partition a Set into Two Subsets of Equal Sum Given an array arr[], the task is to check if it can be partitioned into two parts such that the sum of elements in both parts is the same.Note: Each element is present in either the first subset or the second subset, but not in both.Examples: Input: arr[] = [1, 5, 11, 5]Output: true Explanation: Th
15+ min read
Count of Subsets that can be partitioned into two non empty sets with equal Sum Given an array Arr[] of size N, the task is to find the count of subsets of Arr[] that can be partitioned into two non-empty groups having equal sum. Examples: Input: Arr[] = {2, 3, 4, 5}Output: 2Explanation: The subsets are: {2, 3, 5} which can be split into {2, 3} and {5}{2, 3, 4, 5} which can be
15+ min read
Partition an array into two subsets with equal count of unique elements Given an array arr[] consisting of N integers, the task is to partition the array into two subsets such that the count of unique elements in both the subsets is the same and for each element, print 1 if that element belongs to the first subset. Otherwise, print 2. If it is not possible to do such a
13 min read
Count number of ways to partition a set into k subsets Given two numbers n and k where n represents a number of elements in a set, find a number of ways to partition the set into k subsets.Example: Input: n = 3, k = 2Output: 3Explanation: Let the set be [1, 2, 3], we can partition it into 3 subsets in the following ways [[1,2], [3]], [[1], [2,3]], [[1,3
15+ min read