×

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 Boolean Keyword

Boolean keyword In java programming language we basically have two types of primitive data types, Boolean and Numeric (integer and floating-point data types). In this article we are going to learn...

4 minutes read.

String Manipulation in Java

String Manipulation in Java In Java, string manipulation is a common task performed by programmer. Java String class provides many built-in functions that are used to manipulate string. The manipulation of...

4 minutes read.

Java extend multiple classes

In Java, what does extend mean? One of several Java inheritance keywords is extended, meaning we pass all or most of the Parent class's characteristics through to the Child class. The...

3 minutes read.

Iccanobif Numbers in Java

In this article, you will be very well equipped with the knowledge of iccanobif numbers in Java. You will also know how they are formed and basic example programs on...

3 minutes read.

Set Value to Enum in Java

In this article, you will be acknowledged about Enum in java. Most importantly you will learn how to set value to Enum or how to practically customize a value to...

3 minutes read.

How to check if date is valid in Java?

In this article, you will acknowledge about how to verify if a date is valid or not. For this you will learn the approach, you will be able to write...

3 minutes read.

Delete a Cycle from a Linked List in Java

Assume a method detectAndRemoveLoop(), which examines if a given Linked List includes a loop and, if so, eliminates this Loop and returns true. This returns false if the list does...

7 minutes read.

Tribonacci series in Java

The Fibonacci series and the Tribonacci sequence are linked. The Fibonacci sequence, each element summates the three preceding terms, is expanded into the Tribonacci series in Java. Through specific examples,...

3 minutes read.

Java Buffer Reader

When a variable cannot change its value during run time is called a Static way of programming. In this programming, a variable is directly assigned to a value. Program: Import java.io.*; class  A {  ...

4 minutes read.

Access specifiers in Java

What are access specifiers in Java? Access specifiers in Java are used to determine whether other classes can use a particular field or invoke a particular method. Access specifiers mainly specify...

7 minutes read.

Caesar Cipher Program in Java

It is among the most popular and straightforward encryption methods. With this method, each letter in the text is swapped out for a letter that is a certain number of...

3 minutes read.

Isomorphic String in Java

In this tutorial, we will understand what is meant by isomorphic String in java. We will also see a Java program to find out if the string is isomorphic or...

4 minutes read.

Finding Odd Occurrence of a Number in Java

In this tutorial, we will learn how to find the odd occurrence of a number through a java program. Let us consider an array of non-negative integers. Here, except for one...

6 minutes read.

How Many Ways to Create Objects in Java

Introduction Java comes under the category of object-oriented programming languages. Since it is object-oriented, everything in Java is considered an object. Java is a diverse programming language that is designed to...

6 minutes read.

Interface Program in Java

Interface Program in Java In the previous topic, we discussed that abstraction is possible through the interface and abstract class. An abstract class provides partial to 100% abstraction. 100 %abstraction in...

4 minutes read.

Frugal number in Java

A frugal number is a positive integer with base b that has more digits than the number of prime factors it can be factored into (including exponents greater than 1)....

3 minutes read.

Java Integer numberOfLeadingZeros() method

The numberOfLeadingZeros()  method of Java Integer class returns the total number of zero bits preceding the highest-order one-bit in the 2’s complement binary representation of the specified int value.  Syntax public static...

1 minute read.

Java Boolean logicalAnd() Method

The logicalAnd() method of Java Boolean class returns the result of implementing logicalAND operation on the specified Boolean operands. Syntax:public static boolean logicalAnd (boolean a, boolean b) Parameters:The parameters ‘a’ and ‘b’...

2 minutes read.

Difference between = = and equals ( ) in java

Java : Java is a pure object oriented language. It was introduced by James Gosling in the year 1995. The first public implementation of java was done by sun micro systems...

6 minutes read.

How to Iterate a HashMap in Java?

Hash-map is a class of Java collections framework which has the functionality to implement the Map interface of Java. It stores the data in key-value pairs and can be accessed...

5 minutes read.