Open In App

Subset with sum closest to zero

Last Updated : 11 May, 2021
Comments
Improve
Suggest changes
Like Article
Like
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.
 


Next Article

Similar Reads