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