Meet in the middle in Java


We are provided with an array and a sum value; the problem statement is to calculate the maximum subset sum which does not exceed the given sum value. We cannot apply the brute force approach here because the structure of the given array is not the same as the divide and conquer approach.

Let us see various input output scenarios for this -

Let us understand with example

Input − long arr[] = { 21, 1, 2, 45, 9, 8 } long given_Sum = 12

Output −The maximum sum subset having sum less than or equal to the given sum-->12

Explanation −The array is split into a set of 2 subset. The first having n/2 elements and the later has the rest. All the possible subset sums of the first subset is calculated and stored in the array A and similarly the subset sum of the later subset is calculated and stored in array B. Finally the 2 sub-problem are merged such that their sum is less than or equal to given sum.

Input − long arr[] = { 2, 12, 16, 25, 17, 27 } long given_Sum = 24;

Output −The maximum sum subset having sum less than or equal to the given sum-->19

Explanation −The array is split into a set of 2 subset. The first having n/2 elements and the later has the rest. All the possible subset sums of the first subset is calculated and stored in the array A and similarly the subset sum of the later subset is calculated and stored in array B. Finally the 2 sub-problem are merged such that their sum is less than or equal to given sum.

Approach used in the below program is as follows −

  • Create an array of data type long and a variable of data type long and set it to 10. Call the function as calculateSubsetSum(arr, arr.length, given_Sum)).

  • Inside the method, calculateSubsetSum(arr, arr.length, given_Sum))

    • Call the method as solve_subarray(a, A, len / 2, 0) and solve_subarray(a, B, len - len / 2, len / 2)

    • Calculate the size of A and B and then sort the array B using the sort() method.

    • Start loop FOR from i to 0 till i less than size of an array A. check IF A[i] less than equals to given_Sum then set get_lower_bound to calculate_lower_bound(B, given_Sum - A[i]). Check, IF get_lower_bound to size_B OR B[get_lower_bound] not equals to (given_Sum - A[i])) then decrement get_lower_bound by 1.

    • Check IF B[get_lower_bound] + A[i]) greater than max then set max to B[get_lower_bound] + A[i].

    • return max

  • Inside the method, solve_subarray(long a[], long x[], int n, int c)

    • Start loop FOR from i to 0 till i less than (1 << n). Inside the loop, set sum to 0.

    • Start loop FOR from j to 0 till j less than n. Inside the loop, check IF i & (1 << j)) equals to 0 then set sum to sum + a[j + c].

    • Set x[i] to sum

  • Inside the method, calculate_lower_bound(long a[], long x)

    • Declare variables as left to -1 and right to length of array 1.

    • Start Loop WHILE left + 1 less than right. Inside the while, set m as (left + right) >>> 1. Check IF a[m] greater than x then set right to m.

    • Else, set left to m.

    • Return right.

Example

import java.util.*;
import java.lang.*;
import java.io.*;
public class testClass{
   static long A[] = new long[2000005];
   static long B[] = new long[2000005];
   static void solve_subarray(long a[], long x[], int n, int c){
      for (int i = 0; i < (1 << n); i++){
         long sum = 0;
         for (int j = 0; j < n; j++){
            if ((i & (1 << j)) == 0){
               sum += a[j + c];
            }
         }
         x[i] = sum;
      }
   }
   static long calculateSubsetSum(long a[], int len, long given_Sum){
      solve_subarray(a, A, len / 2, 0);
      solve_subarray(a, B, len - len / 2, len / 2);
      int size_A = 1 << (len / 2);
      int size_B = 1 << (len - len / 2);
      Arrays.sort(B);
      long max = 0;
      for (int i = 0; i < size_A; i++){
         if (A[i] <= given_Sum){
            int get_lower_bound = calculate_lower_bound(B, given_Sum - A[i]);
            if (get_lower_bound == size_B || B[get_lower_bound] != (given_Sum - A[i])){
               get_lower_bound--;
            }
            if((B[get_lower_bound] + A[i]) > max){
               max = B[get_lower_bound] + A[i];
            }
         }
      }
      return max;
   }
   static int calculate_lower_bound(long a[], long x){
      int left = -1, right = a.length;
      while (left + 1 < right){
         int m = (left + right) >>> 1;
         if (a[m] >= x){
            right = m;
         }
         else{
            left = m;
         }
      }
      return right;
   }
   public static void main(String[] args){
      long arr[] = { 21, 1, 2, 45, 9, 8 };
      long given_Sum = 12;
      System.out.println("The maximum sum subset having sum less than or equal to the given sum-->" + calculateSubsetSum(arr, arr.length, given_Sum));
   }
}

Output

If we run the above code it will generate the following Output

The maximum sum subset having sum less than or equal to the given sum-->12

Updated on: 05-Nov-2021

232 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements