Skip to content
Related Articles

Related Articles

Subset with sum closest to zero
  • Difficulty Level : Hard
  • Last Updated : 12 Jun, 2019

Given an array ‘arr’ consisting of integers, the task is to find the non-empty subset such that its sum is closest to zero i.e. absolute difference between zero and the sum is minimum.

Examples:

Input : arr[] = {2, 2, 2, -4}
Output : 0
arr[0] + arr[1] + arr[3] = 0
That’s why answer is zero.

Input : arr[] = {1, 1, 1, 1}
Output : 1

One simple approach is to generate all possible subsets recursively and find the one with the sum closest to zero. Time complexity of this approach will be O(2^n).



A better approach will be using Dynamic programming in Pseudo Polynomial Time Complexity .
Let’s suppose sum of all the elements we have selected upto index ‘i-1’ is ‘S’. So, starting from index ‘i’, we have to find a subset with sum closest to -S.
Let’s define dp[i][S] first. It means sum of the subset of the subarray{i, N-1} of array ‘arr’ with sum closest to ‘-S’.

Now, we can include ‘i’ in the current sum or leave it. Thus we, have two possible paths to take. If we include ‘i’, current sum will be updated as S+arr[i] and we will solve for index ‘i+1’ i.e. dp[i+1][S+arr[i]] else we will solve for index ‘i+1’ directly. Thus, the required recurrence relation will be.

dp[i][s] = RetClose(arr[i]+dp[i][s+arr[i]], dp[i+1][s], -s);
where RetClose(a, b, c) returns a if |a-c|<|b-c| else it returns b

Below is the implementation of the above approach:

C++




#include <bits/stdc++.h>
using namespace std;
  
#define arrSize 51
#define maxSum 201
#define MAX 100
#define inf 999999
   
// Variable to store states of dp
int dp[arrSize][maxSum];
bool visit[arrSize][maxSum];
   
// Function to return the number closer to integer s
int RetClose(int a, int b, int s)
{
    if (abs(a - s) < abs(b - s))
        return a;
    else
        return b;
}
   
// To find the sum closest to zero
// Since sum can be negative, we will add MAX
// to it to make it positive
int MinDiff(int i, int sum, int arr[], int n)
{
   
    // Base cases
    if (i == n)
        return 0;
    // Checks if a state is already solved
    if (visit[i][sum + MAX])
        return dp[i][sum + MAX];
    visit[i][sum + MAX] = 1;
   
    // Recurrence relation
    dp[i][sum + MAX] =  RetClose(arr[i] +
                        MinDiff(i + 1, sum + arr[i], arr, n),
                        MinDiff(i + 1, sum, arr, n), -1 * sum);
   
    // Returning the value
    return dp[i][sum + MAX];
}
  
// Function to calculate the closest sum value
void FindClose(int arr[],int n)
{
    int ans=inf;
  
    // Calculate the Closest value for every
    // subarray arr[i-1:n]
    for (int i = 1; i <= n; i++)
        ans = RetClose(arr[i - 1] +
                MinDiff(i, arr[i - 1], arr, n), ans, 0);
  
    cout<<ans<<endl;
}
   
// Driver function
int main()
{
    // Input array
    int arr[] = { 25, -9, -10, -4, -7, -33 };
    int n = sizeof(arr) / sizeof(int);
     
    FindClose(arr,n);
    return 0;
}

Java




// Java Program for above approach
import java.io.*;
  
class GFG 
{
      
static int arrSize = 51;
static int maxSum = 201;
static int MAX = 100;
static int inf = 999999;
  
// Variable to store states of dp
static int dp[][] = new int [arrSize][maxSum];
static int visit[][] = new int [arrSize][maxSum];
  
// Function to return the number 
// closer to integer s
static int RetClose(int a, int b, int s)
{
    if (Math.abs(a - s) < Math.abs(b - s))
        return a;
    else
        return b;
}
  
// To find the sum closest to zero
// Since sum can be negative, we will add MAX
// to it to make it positive
static int MinDiff(int i, int sum,
                   int arr[], int n)
{
  
    // Base cases
    if (i == n)
        return 0;
          
    // Checks if a state is already solved
    if (visit[i][sum + MAX] > 0 )
        return dp[i][sum + MAX];
    visit[i][sum + MAX] = 1;
  
    // Recurrence relation
    dp[i][sum + MAX] = RetClose(arr[i] +
                        MinDiff(i + 1, sum + arr[i], arr, n),
                        MinDiff(i + 1, sum, arr, n), -1 * sum);
  
    // Returning the value
    return dp[i][sum + MAX];
}
  
// Function to calculate the closest sum value
static void FindClose(int arr[], int n)
{
    int ans = inf;
  
    // Calculate the Closest value for every
    // subarray arr[i-1:n]
    for (int i = 1; i <= n; i++)
        ans = RetClose(arr[i - 1] +
            MinDiff(i, arr[i - 1], 
                       arr, n), ans, 0);
  
        System.out.println(ans);
}
  
// Driver Code
public static void main (String[] args) 
{
  
    // Input array
    int arr[] = { 25, -9, -10, -4, -7, -33 };
    int n = arr.length;
      
    FindClose(arr,n);
}
}
  
// This code is contributed by ajit_00023@ 

Python3




# Python3 Code for above implementation
import numpy as np
  
arrSize = 51 
maxSum = 201 
MAX = 100 
inf = 999999 
  
# Variable to store states of dp 
dp = np.zeros((arrSize,maxSum)); 
visit = np.zeros((arrSize,maxSum)); 
  
# Function to return the number closer to integer s 
def RetClose(a, b, s) : 
  
    if (abs(a - s) < abs(b - s)) :
        return a; 
    else :
        return b; 
  
  
# To find the sum closest to zero 
# Since sum can be negative, we will add MAX 
# to it to make it positive 
def MinDiff(i, sum, arr, n) : 
  
    # Base cases 
    if (i == n) :
        return 0
          
    # Checks if a state is already solved 
    if (visit[i][sum + MAX]) :
        return dp[i][sum + MAX];
          
    visit[i][sum + MAX] = 1
  
    # Recurrence relation 
    dp[i][sum + MAX] = RetClose(arr[i] + 
                        MinDiff(i + 1, sum + arr[i], arr, n), 
                        MinDiff(i + 1, sum, arr, n), -1 * sum); 
  
    # Returning the value 
    return dp[i][sum + MAX]; 
  
  
# Function to calculate the closest sum value 
def FindClose(arr,n) : 
  
    ans=inf; 
  
    # Calculate the Closest value for every 
    # subarray arr[i-1:n] 
    for i in range(1, n + 1) :
        ans = RetClose(arr[i - 1] + 
                MinDiff(i, arr[i - 1], arr, n), ans, 0); 
  
    print(ans); 
  
  
# Driver function 
if __name__ == "__main__"
  
    # Input array 
    arr = [ 25, -9, -10, -4, -7, -33 ]; 
    n = len(arr); 
      
    FindClose(arr,n); 
      
    # This code is contributed by AnkitRai01

C#




// C# Program for above approach
using System;
  
class GFG 
{
      
static int arrSize = 51;
static int maxSum = 201;
static int MAX = 100;
static int inf = 999999;
  
// Variable to store states of dp
static int [,]dp = new int [arrSize,maxSum];
static int [,]visit = new int [arrSize,maxSum];
  
// Function to return the number 
// closer to integer s
static int RetClose(int a, int b, int s)
{
    if (Math.Abs(a - s) < Math.Abs(b - s))
        return a;
    else
        return b;
}
  
// To find the sum closest to zero
// Since sum can be negative, we will add MAX
// to it to make it positive
static int MinDiff(int i, int sum,
                int []arr, int n)
{
  
    // Base cases
    if (i == n)
        return 0;
          
    // Checks if a state is already solved
    if (visit[i,sum + MAX] > 0 )
        return dp[i,sum + MAX];
    visit[i,sum + MAX] = 1;
  
    // Recurrence relation
    dp[i,sum + MAX] = RetClose(arr[i] +
                        MinDiff(i + 1, sum + arr[i], arr, n),
                        MinDiff(i + 1, sum, arr, n), -1 * sum);
  
    // Returning the value
    return dp[i,sum + MAX];
}
  
// Function to calculate the closest sum value
static void FindClose(int []arr, int n)
{
    int ans = inf;
  
    // Calculate the Closest value for every
    // subarray arr[i-1:n]
    for (int i = 1; i <= n; i++)
        ans = RetClose(arr[i - 1] +
            MinDiff(i, arr[i - 1], 
                    arr, n), ans, 0);
  
        Console.WriteLine(ans);
}
  
// Driver Code
public static void Main () 
{
  
    // Input array
    int []arr = { 25, -9, -10, -4, -7, -33 };
    int n = arr.Length;
      
    FindClose(arr,n);
}
}
  
// This code is contributed by  anuj_67.. 
Output:
-1

Time complexity: O(N*S), where N is the number of elements in the array and S is the sum of all the numbers in the array.

My Personal Notes arrow_drop_up
Recommended Articles
Page :