3-partition problem: Given a set S of positive integers, determine if it can be partitioned into three disjoint subsets that all have the same sum, and they cover S.

The 3–partition problem is a special case of the Partition Problem, which is related to the Subset Sum Problem (which itself is a special case of the Knapsack Problem). The goal is to partition S into two subsets with an equal sum in the partition problem. In the 3–partition problem, the goal is to partition S into 3 subsets with an equal sum.

 
For example,

S = { 7, 3, 2, 1, 5, 4, 8 }

We can partition S into three partitions, each having a sum of 10.

S1 = { 7, 3 }
S2 = { 5, 4, 1 }
S3 = { 8, 2 }

Note that there can be multiple solutions to a single set.

Practice this problem

We can start by calculating the sum of all St in the set. If St is not divisible by 3, we can’t divide the array into three subsets with an equal sum. If St is divisible by 3, check if 3 subsets with the sum of elements equal to St/3 exists or not. We can find this by considering each item in the given array one by one, and for each item, there are three possibilities:

  1. Include the current item in the first subset and recur for the remaining items with the remaining sum.
  2. Include the current item in the second subset and recur for the remaining items with the remaining sum.
  3. Include the current item in the third subset and recur for the remaining items with the remaining sum.

The base case of the recursion would be when no items are left. We return true when 3 subsets, each with zero-sum, are found. We can optimize our code by calling case 2 only if case 1 doesn’t result in a solution, and case 3 only if case 1 and 2 don’t result in any solution.

 
The algorithm can be implemented as follows in C++, Java, and Python:

C++


Download  Run Code

Output:

Set can be partitioned

Java


Download  Run Code

Output:

Set can be partitioned

Python


Download  Run Code

Output:

Set can be partitioned

The time complexity of the above solution is exponential and requires additional space for the recursion (call stack).
 

 
The problem has an optimal substructure and also exhibits an overlapping subproblems, i.e., the problem can be split into smaller subproblems, and the same subproblem will get computed again and again. We can easily prove this by drawing a recursion tree of the above code for a huge input.

Dynamic programming can solve this problem by saving subproblem solutions in memory rather than computing them again and again. The following implementation in C++, Java, and Python demonstrates the top-down approach:

C++


Download  Run Code

Output:

Set can be partitioned

Java


Download  Run Code

Output:

Set can be partitioned

Python


Download  Run Code

Output:

Set can be partitioned

The time complexity of the above top-up solution is O(n × sum3) and requires O(n × sum3) extra space, where n is the size of the input and sum is the sum of all elements in the input.

 
Exercise: Extend the solution to k-partitions and print all partitions.