Partition of a set into K subsets with equal sum using BitMask and DP

Last Updated : 11 Aug, 2021

Given an integer array arr[] of consisting of N integers, the task is 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: Yes
Explanation:
Possible subsets of given array are {2, 4}, (1, 5} and {6}
Input: arr[] = {2, 1, 5, 5, 6}, K = 3
Output: No

For the recursive approach, refer to Partition of a set into K subsets with equal sum.
Approach:
Follow the steps below to solve the problem:

• 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:

1. The jth bit is not set in the mask (mask&(1<<j) == 0)
2. 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
Illustration:
arr [ ] = [4, 3, 2, 3, 5, 2, 1], K = 4, tar = 5
dp[“1100101”] implies that { 4, 3, 5, 1 } are chosen
Hence, Sum = 4 + 3 + 5 + 1 = 13, 13 % 5 = 3.
Hence, dp[“1100101”] = 3
If dp[“11111…1111”] == 0 then that means we can find the solution.

Below is the implementation of above approach:

C++

 `// C++ program to check if the` `// given array can be partitioned` `// into K subsets with equal sum` `#include ` `using` `namespace` `std;`   `// Function to check whether` `// K required partitions` `// are possible or not` `bool` `isKPartitionPossible(``int` `arr[],` `                          ``int` `N, ``int` `K)` `{` `    ``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[(1 << 15)];` `    ``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 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) {` `                ``// transition` `                ``dp[mask | (1 << i)]` `                    ``= (dp[mask]` `                       ``+ arr[i])` `                      ``% target;` `            ``}` `        ``}` `    ``}`   `    ``if` `(dp[(1 << N) - 1] == 0)` `        ``return` `true``;` `    ``else` `        ``return` `false``;` `}`   `// Driver Code` `int` `main()` `{` `    ``int` `arr[] = { 2, 1, 4, 5, 3, 3 };` `    ``int` `N = ``sizeof``(arr) / ``sizeof``(arr[0]);` `    ``int` `K = 3;`   `    ``if` `(isKPartitionPossible(arr, N, K)) {` `        ``cout << ``"Partitions into equal "``;` `        ``cout << ``"sum is possible.\n"``;` `    ``}` `    ``else` `{` `        ``cout << ``"Partitions into equal "``;` `        ``cout << ``"sum is not possible.\n"``;` `    ``}` `}`

Java

 `// Java program to check if the` `// given array can be partitioned` `// into K subsets with equal sum` `import` `java.util.*;`   `class` `GFG{`   `// Function to check whether` `// K required partitions` `// are possible or not` `static` `boolean` `isKPartitionPossible(``int` `arr[],` `                                    ``int` `N, ``int` `K)` `{` `    ``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` `<< ``15``)];` `    ``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 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` `(dp[(``1` `<< N) - ``1``] == ``0``)` `        ``return` `true``;` `    ``else` `        ``return` `false``;` `}`   `// Driver Code` `public` `static` `void` `main(String[] args)` `{` `    ``int` `arr[] = { ``2``, ``1``, ``4``, ``5``, ``3``, ``3` `};` `    ``int` `N = arr.length;` `    ``int` `K = ``3``;`   `    ``if` `(isKPartitionPossible(arr, N, K))` `    ``{` `        ``System.out.print(``"Partitions into equal "``);` `        ``System.out.print(``"sum is possible.\n"``);` `    ``}` `    ``else` `    ``{` `        ``System.out.print(``"Partitions into equal "``);` `        ``System.out.print(``"sum is not possible.\n"``);` `    ``}` `}` `}`   `// This code is contributed by Amit Katiyar`

Python3

 `# Python3 program to check if the` `# given array can be partitioned` `# into K subsets with equal sum`   `# Function to check whether` `# K required partitions` `# are possible or not` `def` `isKPartitionPossible(arr, N, K):` `    `  `    ``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`   `    ``sum` `=` `0` `    ``for` `i ``in` `range``(N):` `        ``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` `    ``target ``=` `sum` `/` `K`   `    ``# Initialize dp array with -1` `    ``dp ``=` `[``0` `for` `i ``in` `range``(``1` `<< ``15``)]` `    ``for` `i ``in` `range``((``1` `<< N)):` `        ``dp[i] ``=` `-``1`   `    ``# Sum of empty subset` `    ``# is zero` `    ``dp[``0``] ``=` `0`   `    ``# Iterate over all subsets/masks` `    ``for` `mask ``in` `range``((``1` `<< N)):` `        `  `        ``# If 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` `(dp[(``1` `<< N) ``-` `1``] ``=``=` `0``):` `        ``return` `True` `    ``else``:` `        ``return` `False`   `# Driver Code` `if` `__name__ ``=``=` `'__main__'``:` `    `  `    ``arr ``=` `[ ``2``, ``1``, ``4``, ``5``, ``3``, ``3` `]` `    ``N ``=` `len``(arr)` `    ``K ``=` `3`   `    ``if` `(isKPartitionPossible(arr, N, K)):` `        ``print``(``"Partitions into equal "``\` `              ``"sum is possible."``)` `    ``else``:` `        ``print``(``"Partitions into equal sum "``\` `              ``"is not possible."``)`   `# This code is contributed by Surendra_Gangwar`

C#

 `// C# program to check if the` `// given array can be partitioned` `// into K subsets with equal sum` `using` `System;`   `class` `GFG{`   `// Function to check whether` `// K required partitions` `// are possible or not` `static` `bool` `isKPartitionPossible(``int` `[]arr,` `                                 ``int` `N, ``int` `K)` `{` `    ``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 << 15)];` `    ``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 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` `(dp[(1 << N) - 1] == 0)` `        ``return` `true``;` `    ``else` `        ``return` `false``;` `}`   `// Driver Code` `public` `static` `void` `Main(String[] args)` `{` `    ``int` `[]arr = { 2, 1, 4, 5, 3, 3 };` `    ``int` `N = arr.Length;` `    ``int` `K = 3;`   `    ``if` `(isKPartitionPossible(arr, N, K))` `    ``{` `        ``Console.Write(``"Partitions into equal "``);` `        ``Console.Write(``"sum is possible.\n"``);` `    ``}` `    ``else` `    ``{` `        ``Console.Write(``"Partitions into equal "``);` `        ``Console.Write(``"sum is not possible.\n"``);` `    ``}` `}` `}`   `// This code is contributed by Amit Katiyar`

Javascript

 ``

Output:

`Partitions into equal sum is possible.`

Time Complexity: O (N * 2 N)
Auxiliary Space: O (2 N)