Given an integer array arr[], divide it into two subsets such that the absolute difference between their sums is zero (i.e., both subsets have the same sum).
- If the size of the array is even, each subset must contain exactly n/2 elements.
- If the size of the array is odd, then one subset must contain n/2 elements and the other must contain (n+1)/2 elements.
Note: It is always guaranteed that the array can be divided into two such subsets.
Examples:
Input: arr[] = [1, 2, 3, 4]
Output: [[1, 4], [2, 3]]
Explanation: The absolute difference between the sum of both subsets is 0Input: arr[] = [5, 10, 15]
Output: [[5, 10], [15]]
Explanation: The absolute difference between the sum of both subsets is 0
[Approach] Using Recursion and Backtracking - O(2n) Time and O(n) Space
The idea is to reduce the partitioning problem into finding one subset of required size whose sum equals half of the total sum. The other subset is simply the remaining elements.
How to find the subset whose sum is equals to half of total sum?
First calculate the total sum of the array. Since equal division is guaranteed, the sum must be even, and the target for each subset is totalSum / 2.
Then, recursively search for one subset of size n/2 (n/2 or n/2+1 if n is odd) whose sum equals the target.
At each step, we either include the current element in the subset or skip it.
When the subset reaches required size and sum, we stop and store the result.
#include <iostream>
#include <vector>
using namespace std;
// Recursive function to find a subset with sum = total/2
bool findSubset(vector<int>& arr, int i, int target,int total,
vector<int>& result) {
int n = arr.size();
if (target == total/2 &&
((n % 2 == 0 && result.size() == n / 2) ||
(n % 2 != 0 && (result.size() == n / 2 || result.size() == n / 2 + 1)))) {
return true;
}
if (i >= n) return false;
// include current element
result.push_back(i);
if(findSubset(arr, i + 1, target + arr[i], total, result)){
return true;
}
// Backtrack
result.pop_back();
// exclude current element
if(findSubset(arr, i + 1, target, total, result)){
return true;
}
return false;
}
vector<vector<int>> equalPartition(vector<int>& arr) {
int n = arr.size();
int total = 0;
for (int x : arr) total += x;
int target = 0;
vector<int> result;
vector<vector<int>> res(2);
// Storing result if possible
if(findSubset(arr, 0, target, total, result)) {
int k = 0;
for (int i = 0; i < n; i++) {
if (k < result.size() && i == result[k]) {
res[0].push_back(arr[i]);
k++;
}
else res[1].push_back(arr[i]);
}
}
return res;
}
int main() {
vector<int> arr = {1, 2, 3,4};
vector<vector<int>> res = equalPartition(arr);
for (auto& subset : res) {
for (int x : subset) cout << x << " ";
cout << "\n";
}
}
import java.util.ArrayList;
import java.util.List;
class GFG {
// Recursive function to find a subset with sum = total/2
static boolean findSubset(int[] arr, int i, int target, int total,
ArrayList<Integer> result) {
int n = arr.length;
if (target == total / 2 &&
((n % 2 == 0 && result.size() == n / 2) ||
(n % 2 != 0 && (result.size() == n / 2 || result.size() == n / 2 + 1)))) {
return true;
}
if (i >= n) return false;
// include current element
result.add(i);
if (findSubset(arr, i + 1, target + arr[i], total, result)) return true;
// Backtrack
result.remove(result.size() - 1);
// exclude current element
if (findSubset(arr, i + 1, target, total, result)) return true;
return false;
}
// Function to partition array into two equal-sum subsets
static ArrayList<ArrayList<Integer>> equalPartition(int[] arr) {
int n = arr.length;
int total = 0;
for (int x : arr) total += x;
ArrayList<Integer> result = new ArrayList<>();
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
res.add(new ArrayList<>());
res.add(new ArrayList<>());
// Storing result if possible
if (findSubset(arr, 0, 0, total, result)) {
int k = 0;
for (int i = 0; i < n; i++) {
if (k < result.size() && i == result.get(k)) {
res.get(0).add(arr[i]);
k++;
} else {
res.get(1).add(arr[i]);
}
}
}
return res;
}
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4};
ArrayList<ArrayList<Integer>> res = equalPartition(arr);
for (ArrayList<Integer> subset : res) {
for (int x : subset) System.out.print(x + " ");
System.out.println();
}
}
}
def findSubset(arr, i, target, total, result):
n = len(arr)
if target == total // 2 and ((n % 2 == 0 and len(result) == n // 2) or
(n % 2 != 0 and (len(result) == n // 2 or len(result) == n // 2 + 1))):
return True
if i >= n:
return False
# include current element
result.append(i)
if findSubset(arr, i + 1, target + arr[i], total, result):
return True
# Backtrack
result.pop()
# exclude current element
if findSubset(arr, i + 1, target, total, result):
return True
return False
def equalPartition(arr):
n = len(arr)
total = sum(arr)
target = 0
result = []
# subset 0 and subset 1
res = [[], []]
# Storing result if possible
if findSubset(arr, 0, target, total, result):
k = 0
for i in range(n):
if k < len(result) and i == result[k]:
res[0].append(arr[i])
k += 1
else:
res[1].append(arr[i])
return res
if __name__ =="__main__":
arr = [1, 2, 3,4]
res = equalPartition(arr)
for subset in res:
print(" ".join(map(str, subset)))
using System;
using System.Collections.Generic;
class GFG {
// Recursive function to find a subset with sum = total/2
static bool findSubset(int[] arr, int i, int target, int total, List<int> result) {
int n = arr.Length;
if (target == total / 2 &&
((n % 2 == 0 && result.Count == n / 2) ||
(n % 2 != 0 && (result.Count == n / 2 || result.Count == n / 2 + 1)))) {
return true;
}
if (i >= n) return false;
// include current element
result.Add(i);
if (findSubset(arr, i + 1, target + arr[i], total, result)) return true;
// Backtrack
result.RemoveAt(result.Count - 1);
// exclude current element
if (findSubset(arr, i + 1, target, total, result)) return true;
return false;
}
// Function to partition array into two equal-sum subsets
static List<List<int>> equalPartition(int[] arr) {
int n = arr.Length;
int total = 0;
foreach (int x in arr) total += x;
List<int> result = new List<int>();
List<List<int>> res = new List<List<int>> { new List<int>(), new List<int>() };
// Storing result if possible
if (findSubset(arr, 0, 0, total, result)) {
int k = 0;
for (int i = 0; i < n; i++) {
if (k < result.Count && i == result[k]) {
res[0].Add(arr[i]);
k++;
} else {
res[1].Add(arr[i]);
}
}
}
return res;
}
static void Main() {
int[] arr = { 1, 2, 3, 4 };
List<List<int>> res = equalPartition(arr);
foreach (var subset in res) {
foreach (int x in subset) Console.Write(x + " ");
Console.WriteLine();
}
}
}
// Recursive function to find a subset with sum = total/2
function findSubset(arr, i, target, total, result) {
const n = arr.length;
if (target === Math.floor(total / 2) &&
((n % 2 === 0 && result.length === Math.floor(n / 2)) ||
(n % 2 !== 0 && (result.length === Math.floor(n / 2) ||
result.length === Math.floor(n / 2) + 1)))) {
return true;
}
if (i >= n) return false;
// include current element
result.push(i);
if (findSubset(arr, i + 1, target + arr[i], total, result)) return true;
// Backtrack
result.pop();
// exclude current element
if (findSubset(arr, i + 1, target, total, result)) return true;
return false;
}
// Function to partition array into two equal-sum subsets
function equalPartition(arr) {
const n = arr.length;
const total = arr.reduce((a, b) => a + b, 0);
const result = [];
// subset 0 and subset 1
const res = [[], []];
// Storing result if possible
if (findSubset(arr, 0, 0, total, result)) {
let k = 0;
for (let i = 0; i < n; i++) {
if (k < result.length && i === result[k]) {
res[0].push(arr[i]);
k++;
} else {
res[1].push(arr[i]);
}
}
}
return res;
}
// Driver code
const arr = [1, 2, 3, 4];
const res = equalPartition(arr);
for (const subset of res) {
console.log(subset.join(' '));
}
Output
2 3 1 4