The solution to this problem involves the subset sum problem.
If there exists a way to sum to half of the total sum of the array, then we can set all of those numbers to be negative. The rest of the numbers will then be positive. Because each of these subsets sum to half of the total sum, their respective sum will thus be 0.
Here is the code in c++:
#include<stdio.h>
int arr[] = {1, 2, 2, 3, 4};
int n = 5; // size of arr
int sum = 0;
// dp array only needs to be [n + 1][total sum + 1] big
bool dp[30][100];
inline void subset_sum(){
for (int i = 0; i <= sum; i++)
dp[0][i] = false;
for (int i = 0; i <= n; i++)
dp[i][0] = true;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= sum; j++) {
dp[i][j] = dp[i - 1][j];
if (arr[i - 1] <= j)
dp[i][j] |= dp[i - 1][j - arr[i - 1]];
}
}
}
int main(){
for (int i = 0; i < n; i++)
sum += arr[i];
// run subset sum dp using a bottom-up approach
// True = sum is possible, False = not possible
subset_sum();
int max_half;
for (int i = sum / 2; i>=1; i--){
if (dp[n][i]){ // it is possible to sum to i using values in arr
max_half = i;
break;
}
}
// output will be the closest sum of positives
// and negatives to 0
printf("%d\n", 2 * max_half - sum);
return 0;
}
The output for this code would be closest possible sum of combinations of positives and negative numbers in the set to 0.
The 2 * max_half - sum
can be derived from max_half - (sum - max_half)
, which would be our best possible sum minus the rest of the numbers.
Here are some examples of different sets of numbers and their respective outputs:
Set: {1, 2, 2, 3, 4}
, output: 0
.
Set: {1, 1, 1, 1, 1}
, output: -1
.
Set: {5, 2, 6, 8, 9, 2}
, output: 0
.
Set: {1, 50}
, output: -49
.
There are many explanations for the subset sum problem on the internet, so I will not explain it here.
The time complexity of this code is O(n * sum), and the space complexity is O(n * sum).
It is also possible to sacrifice some time complexity to improve space complexity, by using a 1 dimensional dp array.