class Solution { /** Recursive code */ static boolean equalPartition(int arr[]) { int n = arr.length; int sum = 0; for(int ele : arr) sum += ele; // if even sum -- then we can divide if(sum%2 != 0) return false; sum = sum/2; return findSubsetSum(arr, sum, n); } static boolean findSubsetSum(int[] arr, int sum, int n) { // when we reach end of the array, so couldn't found a subset if(n == 0) return false; // when sum becomes 0 that means found a subset if(sum == 0) return true; if(arr[n-1] <= sum) { // pick the element in subset boolean pick = findSubsetSum(arr, sum - arr[n-1], n-1); // do not pick the element in subset boolean notPick = findSubsetSum(arr, sum, n-1); return pick || notPick; } // when current element exceeds given sum, so skip the element return findSubsetSum(arr, sum, n-1); } /** Memoization code */ static boolean equalPartition(int arr[]) { int n = arr.length; int sum = 0; for(int ele : arr) sum += ele; // if even sum -- then we can divide if(sum%2 != 0) return false; sum = sum/2; boolean[][] t = new boolean[n+1][sum+1]; // when array of size will increase but sum needs to always 0, then we can have always empty subset for(int i=0; i<n+1; i++) { } // when sum increases but size of array is always 0, then we cannot have any subset for(int j=0; j<n+1; j++) { } return findSubsetSum(arr, sum, n, t); } static boolean findSubsetSum(int[] arr, int sum, int n, boolean[][] t) { // when we reach end of the array, so couldn't found a subset if(n == 0) return false; // when sum becomes 0 that means found a subset if(sum == 0) return true; if(t[n][sum] != false) return t[n][sum]; if(arr[n-1] <= sum) { // pick the element in subset boolean pick = findSubsetSum(arr, sum - arr[n-1], n-1, t); // do not pick the element in subset boolean notPick = findSubsetSum(arr, sum, n-1, t); t[n][sum] = pick || notPick; return t[n][sum]; } // when current element exceeds given sum, so skip the element t[n][sum] = findSubsetSum(arr, sum, n-1, t); return t[n][sum]; } /** Top-down approach */ static boolean equalPartition(int arr[]) { int n = arr.length; int sum = 0; for(int ele : arr) sum += ele; // if even sum -- then we can divide if(sum%2 != 0) return false; sum = sum/2; boolean[][] t = new boolean[n+1][sum+1]; // intialise the matrix on basis of base condition for(int i=0; i<n+1; i++) { for(int j=0; j<sum+1; j++) { // when sum increases but size of array is always 0, then we cannot have any subset if(i==0) { t[i][j] = false; } // when array of size will increase but sum needs to always 0, then we can have always empty subset if(j==0) { t[i][j] = true; } } } for(int i=1; i<n+1; i++) { for(int j=1; j<sum+1; j++) { if(arr[i-1] <= j) { boolean pick = t[i-1][j - arr[i-1]]; boolean notPick = t[i-1][j]; t[i][j] = pick || notPick; } else t[i][j] = t[i-1][j]; } } return t[n][sum]; }