Open In App

Subset with sum closest to zero

Last Updated : 11 May, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

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 :
arr[0] + arr[1] + arr[3] = 0 
That’s why answer is zero.
Input : arr[] = {1, 1, 1, 1} 
Output :
 

 

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..


Javascript




<script>
    // Javascript Program for above approach
     
    let arrSize = 51;
    let maxSum = 201;
    let MAX = 100;
    let inf = 999999;
 
    // Variable to store states of dp
    let dp = new Array(arrSize);
    let visit = new Array(arrSize);
     
    for(let i = 0; i < arrSize; i++)
    {
        dp[i] = new Array(maxSum);
        visit[i] = new Array(maxSum);
        for(let j = 0; j < maxSum; j++)
        {
            dp[i][j] = 0;
            visit[i][j] = 0;
        }
    }
     
 
    // Function to return the number
    // closer to integer s
    function RetClose(a, b, 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
    function MinDiff(i, sum, arr, 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
    function FindClose(arr, n)
    {
        let ans = inf;
 
        // Calculate the Closest value for every
        // subarray arr[i-1:n]
        for (let i = 1; i <= n; i++)
            ans = RetClose(arr[i - 1] +
                MinDiff(i, arr[i - 1],
                           arr, n), ans, 0);
 
            document.write(ans);
    }
     
    // Input array
    let arr = [ 25, -9, -10, -4, -7, -33 ];
    let n = arr.length;
       
    FindClose(arr,n);
 
</script>


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.
 



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads