×

Three Partition Problems in Java

In talks with leading IT organizations like Google, Amazon, TCS, Accenture, etc., this extremely intriguing subject is constantly brought up. The goal of the problem-solving exercise is to evaluate the interviewee's logical reasoning, critical thinking, and problem-solving abilities. Therefore, we will solve the three partition problems in Java using various strategies and logic in this section. Additionally, we'll write Java programs for the same.

Problem Statement

There is a list of positive numbers. It is our job to determine the extent to which the input array can be divided into three fully distinct subsets so that the sum of each of the elements in one subset equals the sum of each of the elements in the other subset. Keep in mind that the input array must contain every element. Show the proper messages just on the console in accordance.

Example 1:

Input

int inputArr[] = {3, 7, 6, 4, 2, 8}

Output: Three separate subsets with an equal number of elements each can be created from the input array that is given.

Consider the following subsets, for clarification.

Sum of Subset1 = "3, 7" is 3 + 7 = 10, Subset2 = 6,4 total = 6 + 4 equals 10,

Sum = 2 + 8 = 10 for subset3 = "2, 8"

As a result, it is clear that we received three equal-sized subsets of the items.

Example 2:

Input

int inputArr[] = {6, 2, 3, 9, 8, 18, 96}

Output: It is impossible to divide the input array into three separate subsets that each have the same number of elements.

Reason: For the specified input array, no set of three subsets will produce an equal number of elements.

Recursive Methodology

First, we'll determine whether the input array's total number of elements is indeed a multiple of three or not. The partition cannot be done if the number is not a multiple of 3. If so, we must determine whether or not three disjoint sets exist were the sum of elements was equal to (the total sum of the input array's elements) / 3. It can be discovered by carefully examining each component of an input array individually. You have the following three options for each element:

  1. Take into account the element from the first subset before recursively finding the other elements.
  2. Take into account the component of the second subset and use recursion on the other components.
  3. Recursion is used to find the other elements after taking into account an element for such a third subset. The test scenario of the recursion will indeed be reached when all of the input array's items have been taken into account because we must take into account every item. Whenever three disjoint subsets were discovered, the recursion may return true.

ThreePartitionExpl1.java

public class ThreePartitionExpl1 
{  
    // An aid for solving the three-partition problem. 
    // There are three disjoint subsets with both the 
    // total if it returns true.  
    public boolean disjointSubsetSum(int a[], int s, int j, int k, int l)  
    {  
        // if the subgroup is found, return true.  
        if (j == 0 && k == 0 && l == 0)   
        {  
            return true;  
        }  
   
        // handling the simplest scenario: removing all objects  
        if (s < 0)   
        {  
            return false;  
        }  
   
        // Case 1: The present element is contained in the first subset.
        boolean case1 = false;  
        if (j - a[s] >= 0) {  
            case1 = disjointSubsetSum(a, s - 1, j - a[s], k, l);  
        }  
   
        // Case 2: The present element is contained in the second subset.  
        boolean case2 = false;  
        if (!case1 && (k - a[s] >= 0))   
        {  
            case2 = disjointSubsetSum(a, s - 1, j, k - a[s], l);  
        }  
   
        // Case 3: The present element is contained in the third subset. 
        boolean case3 = false;  
        if ((!case1 && !case2) && (l - a[s] >= 0))   
        {  
            case3 = disjointSubsetSum(a, s - 1, j, k, l - a[s]);  
        }  
   
        // We can return true if any one of the three scenarios is true.
        return case1 || case2 || case3;  
    }  
   
    // a formula for solving the three 
    // partitions problem. If the given 
    // set a[0... n - 1] can be divided 
    // into the set of three disjoint 
    // subsets that have the same total,
   // the function returns true.
    public boolean partitionInThree(int a[])  
    {  
        // It follows that the supplied array 
// must have at least three members for 
// each of the three disjoint subgroups. 
        if (a.length < 3)   
        {  
            return false;  
        }  
   
        // find the total of all the elements in the specified array.
        int sumOfElements = 0;  
        for(int j = 0; j < a.length; j++)  
        {  
            sumOfElements = sumOfElements + a[j];  
        }  
   
        // return true if the input array can be 
// partitioned into three disjoint subsets 
// with equal sums and the sum of all of the 
// elements have been divisible by three.
        if((sumOfElements % 3) == 0)  
        {  
            if (disjointSubsetSum(a, a.length - 1, sumOfElements / 3, sumOfElements / 3, sumOfElements / 3))  
            {  
            return true;  
            }  
            return false;  
        }  
        return false;  
    }  
   
    // Driver code  
    public static void main(String args[])  
    {  
        // creating an instance for the class   
        ThreePartitionExpl1 o = new ThreePartitionExpl1();  
          
        // First input  
        int a[] = {3, 7, 6 , 4 , 2 , 8};  
          
        int s = a.length;  
          
        System.out.println(" Regarding the input array: ");  
        for(int j = 0; j < s; j++)  
        {  
            System.out.print(a[j]+ " ");  
        }  
        System.out.println();  
        if (o.partitionInThree(a))   
        {  
            System.out.println(" It can be divided into three separate subsets that are mutually exclusive.");  
        }  
        else   
        {  
            System.out.println(" It cannot be divided into three separate subsets that are mutually exclusive.");  
        }  
          
        System.out.println();  
          
        // second input  
        int a2[] = {6, 2, 3, 9, 8, 18, 96};  
        s = a2.length;  
        System.out.println(" Regarding the input array: ");  
        for(int j = 0; j < s; j++)  
        {  
            System.out.print(a2[j]+ " ");  
        }  
        System.out.println();  
        if (o.partitionInThree(a2))   
        {  
            System.out.println(" It can be divided into three separate subsets that are mutually exclusive.");  
        }  
        else   
        {  
            System.out.println(" It cannot be divided into three separate subsets that are mutually exclusive.");  
        }  
    }  
}  

Output:

Three Partition Problems in Java

Analysis of Complexity: The program mentioned above has exponential time complexity.

The aforementioned application produces the desired results; however, it takes a long time. As a result, it cannot effectively handle a huge input.

Using Dynamic Programming

With the use of dynamic programming, we can lessen the temporal complexity. Take note of the program below.

ThreePartitionExpl2.java

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
 
class ThreePartitionExpl2
{
    // aid in resolving the three partition problem. 
    // If there are three subsets with both the 
    // specified total, it returns true.
    public static boolean subsetSum(int[] S1, int n1, int a1, int b1, int c1,
                                    Map<String, Boolean> h1)
    {
        // if the subgroup is found, return true.
        if (a1 == 0 && b1 == 0 && c1 == 0) {
            return true;
        }
 
        // base scenario: nothing is left
        if (n1 < 0) {
            return false;
        }
 
        // create a distinct map key from dynamic input components.
        String key = a1 + "|" + b1 + "|" + c1 + "|" + n1;
 
        // Solve the subproblem if it 
        // appears for the very first time, 
        // then save the solution in a map.
        if (!h1.containsKey(key))
        {
            // Case 1. The current item joins the first subset.
            boolean case1 = false;
            if (a1 - S1[n1] >= 0) {
                case1 = subsetSum(S1, n1 - 1, a1 - S1[n1], b1, c1, h1);
            }
 
            // Case 2. The current item joins the second subset.
            boolean case2 = false;+
            if (!case1 && (b1 - S1[n1] >= 0)) {
                case2 = subsetSum(S1, n1 - 1, a1, b1 - S1[n1], c1, h1);
            }
 
            // Case 3. The current item joins the third subset.
            boolean case3 = false;
            if ((!case1 && !case2) && (c1 - S1[n1] >= 0)) {
                case3 = subsetSum(S1, n1 - 1, a1, b1, c1 - S1[n1], h1);
            }
 
            // return true when we are successful.
            h1.put(key, case1 || case2 || case3);
        }
 
        // bring back the map's subproblem resolution
        return h1.get(key);
    }
 
    // Function to solve the three-partitioning puzzle.
   //  If the supplied set "S" can be partitioned into 
   // three subsets with just an equal sum, then it returns "true."
    public static boolean partition(int[] S1)
    {
        if (S1.length < 3) {
            return false;
        }
 
        // make a map to keep answers to a subproblem.
        Map<String, Boolean> h1 = new HashMap<>();
 
        // find the total of all the set's elements
        int s = Arrays.stream(S1).sum();
        // if the total is divisible by three and
       //  the set "S" can be partitioned into 
       // three subsets with equal sums, then return true.
        return (s % 3) == 0 && subsetSum(S1, S1.length - 1, s/3,
                        s/3, s/3, h1);
    }
 
    public static void main(String[] args)
    {
        // Input: a set of integers
        int[] S1 = { 7, 3, 2, 1, 5, 4, 8 };
 
        if (partition(S1)) {
            System.out.println(" Set may be divided. ");
        }
        else {
            System.out.println(" Set may not be divided. ");
        }
    }
}  

Output:

Three Partition Problems in Java

Complexity analysis: The running time of the aforementioned program is O(sum3 n) and it also uses extra space of O(sum3 n), where the sum is indeed the sum of all the input array's elements and n is the array's total number of elements.

The Problem's Expansion

To print all three disjoint subsets with sums that are equal is another question an interviewer might ask. The items of the disjoint subset must be tracked by an array in this case. Watch the program that comes next.

// ThreePartitionExpl3.java

public class ThreePartitionExpl3  
{  
    // An aid for solving the three-partition problem. 
    // There are three disjoint subsets with both the 
    // total if it returns true.  
    public boolean disjointSubsetSum(int a[], int s, int j, int k, int l, int store[])  
    {  
        // if the subgroup is found, return true. 
        if (j == 0 && k == 0 && l == 0)   
        {  
            return true;  
        }  
   
        // handling the simplest scenario: removing all objects  
        if (s < 0)   
        {  
            return false;  
        }  
          
  
        // Case 1: The current element is contained in the first subset. 
        boolean case1 = false;  
        if (j - a[s] >= 0)   
        {  
            // tracking the current component. 1 denotes the initial subset. 
            store[s] = 1;  
            case1 = disjointSubsetSum(a, s - 1, j - a[s], k, l, store);  
        }  
   
        // Case 2: The current element is contained in the second subset.  
        boolean case2 = false;  
        if (!case1 && (k - a[s] >= 0))   
        {  
            // tracking the current component. 2 denotes the second subset.
            store[s] = 2;  
            case2 = disjointSubsetSum(a, s - 1, j, k - a[s], l, store);  
        }  
   
        // Case 3: The current element is contained in the third subset.  
        boolean case3 = false;  
        if ((!case1 && !case2) && (l - a[s] >= 0))   
        {  // tracking the current component. 3 denotes the third subset.  
            store[s] = 3;  
            case3 = disjointSubsetSum(a, s - 1, j, k, l - a[s], store);  
        }  
   
        return (case1 || case2 || case3) ;  
    }  
   
    // a formula for solving the three partitions problem. 
    // If the given set a[0... n - 1] can be divided 
    // into a series of three disjoint subsets that have 
    // the same total, the function returns true.  
    public boolean partitionInThree(int a[], int s[])  
    {  
        // For the three disparate subsets, it is evident.
       //  The provided array must include at least three elements. 
        if (a.length < 3)   
        {  
            return false;  
        }  
        // find the total of all the elements in the specified array.  
        int sumOfElements = 0;  
        for(int j = 0; j < a.length; j++)  
        {  
            sumOfElements = sumOfElements + a[j];  
        }  
        // return true if the input array can be partitioned 
        // into three disjoint subsets with equal sums and the 
        // sum of all of the elements is divisible by three. 
        if((sumOfElements % 3) == 0)  
        {  
            if (disjointSubsetSum(a, a.length - 1, sumOfElements / 3, sumOfElements / 3, sumOfElements / 3, s))  
            {  
            return true;  
            }  
            return false;  
        }  
        return false;  
    }  
    void display(int a[], int s[])  
    {  
        // the dividers in print  
        for (int k = 0; k < 3; k++)  
        {  
            System.out.print(" Partition " + k + " is ");  
            for (int l = 0; l < a.length; l++)  
            {  
                if (s[l] == k + 1) {  
                    System.out.print(a[l] + " ");  
                }  
            }  
            System.out.println();  
        }  
    }  
    // driver code  
    public static void main(String args[])  
    {  
        // creating an instance for the class   
        ThreePartitionExpl3 o = new ThreePartitionExpl3();  
        // first input  
        int a[] = {3, 7, 1, 2, 4, 5, 8};  
        int s = a.length;  
        // to keep track of the components of both the disjoint subsets  
        int[] store = new int[a.length];  
          
        System.out.println(" Regarding the input array: ");  
        for(int j = 0; j < s; j++)  
        {  
            System.out.print(a[j]+ " ");  
        }  
        System.out.println();  
        if (o.partitionInThree(a, store))   
        {  
            System.out.println(" It could be divided into three separate subsets. ");  
            o.display(a, store);  
        }  
        else   
        {  
            System.out.println(" It could not be divided into three separate subsets. ");  
        }  
        System.out.println();  
        // second input 
        int a2[] = {6, 2, 3, 9, 8, 18, 96};  
        s = a2.length;  
        System.out.println("  Regarding the input array: ");  
        for(int j = 0; j < s; j++)  
        {  
            System.out.print(a2[j]+ " ");  
        }  
        System.out.println();  
        if (o.partitionInThree(a2, store))   
        {  
            System.out.println(" It could be divided into three separate subsets. ");  
        }  
        else   
        {  
            System.out.println(" It could not be divided into three separate subsets. ");  
        }  
    }  
}

Output:

Three Partition Problems in Java

Related Topics

Java Programming certification

The most common technology utilized in the creation of applications is Java. People and businesses like it because it turns original ideas into useful software solutions. A Java programming certification can...

6 minutes read.

Java 9 Tutorial

The Java 9 is most popular release of java programming to make it platform modular. It is used to improve JDK and java implementation security. It provides JAVA SE and...

3 minutes read.

Java Read File

Java provides its users with many ways of reading a file. To read a text file, you can use a FileReader, BufferedReader, or Scanner. Each utility offers something special for...

6 minutes read.

How to download and install Eclipse in Windows?

Download and Install Eclipse on Windows Eclipse is an open source IDE (Integrated Development Environment) which is used to help the programmers to provide a platform to write and run the...

1 minute read.

Buffer reader to read string in Java

The Buffered Reader class of Java is used to read the stream of characters from the input stream. Program to read string using Buffer reader import java.io.*; class  Demo {   public static void main(String...

3 minutes read.

Matrix Multiplication Program in Java

Matrix Multiplication Program in Java The matrix multiplication program in Java is the continuation of the matrix program in Java that we have already discussed earlier. In this section, we will...

3 minutes read.

New Features of Java 14

 Features like Switch expressions and text blocks which are previewed in Java 13 version are standardized in Java 14. Features in Java 14 Switch ExpressionText BlocksRecordsNull Pointer ExceptionsInstance ofPackaging ToolGarbage collectors 1.Switch Expressions Switch...

3 minutes read.

How to Convert Decimal to Hexadecimal in Java

How to Convert Decimal to Hexadecimal in Java The hexadecimal number uses 16 values to represent a number. Numbers from 0 to 9 represented by digits and the numbers from 10...

3 minutes read.

Convert List to String in Java

We occasionally need to create a string from a list of characters. Since a string is only a collection of characters, a character array can be converted into a string....

6 minutes read.

Thread Program in Java

Thread Program in Java Thread program in Java is the continuation of multithreading program in Java. In this topic, we will learn about the usage of threads, race condition in multithreading,...

8 minutes read.

Creation of Multi Thread in java

What are threads in Java? We can use threads to facilitate parallel processing. Threads are helpful when you wish to execute several pieces of code concurrently. A thread is a small process...

3 minutes read.

Differences between Byte Code and Machine Code

This tutorial will discuss the differences between Byte Code and Machine Code. Before that, let's try to know what byte and machine code is. Introduction Every computer has a set of instructions...

4 minutes read.

Hashing Algorithm in Java

The hashing algorithm is a method that maps data to the fixed-length hash. The Java hash-based algorithm employs a cryptographic mathematical operation. A hash technique or hash function is supposed...

8 minutes read.

Constructor Overloading in Java

In Java, constructors can be overloaded just like methods. The idea of having multiple constructors with various parameter sets so that each function Object()  can carry out a particular task...

3 minutes read.

Collections in Java

Collection framework is one of Java's most powerful subsystems. It is a set of classes and interfaces that is all-the-rage technology for superintending objects and a group of objects. In...

6 minutes read.

Spliterator in Java 8

In this tutorial, we will understand the meaning of spliterator in java 8. It is just like any other iterator available in java used to traverse the elements of either...

4 minutes read.

Java concurrency interview questions

During technical interviews, one of the most challenging and sophisticated subjects is concurrency in Java. This page offers responses to some of the related interview questions you might come across. 1....

11 minutes read.

Java Integer class

The Integer class wraps a primitive int type value in an object. Its object contains only a single field whose type is int. Methods: The java.lang.Integer class provides several different methods for...

4 minutes read.

Java class class

Java Class class instances are an executing Java application's implementation of the classes and interfaces. As well as, every Array is indeed an object that is common for all Arrays...

6 minutes read.

Binary Search Java

Binary search is a search mechanism for key elements from the given List/Array. In Binary search, the search mechanism is followed by dividing the array into parts; hence the search...

3 minutes read.