I'm given the equation like this one:
n = 7
1 + 1 - 4 - 4 - 4 - 2 - 2
How can I optimally replace operators, so that the sum of the equation is equal to zero, or print -1
.
I think of one algorithm, but it is not optimal. I have an idea to bruteforce all cases with complexity O(n*2^n)
, but (n < 300)
.
Here is the link of the problem: http://codeforces.com/gym/100989/problem/M.
A Simple solution is to run two loop to split array and check it is possible to split array into two parts such that sum of first_part equal to sum of second_part. Below is the implementation of above idea.
Traverse the array from start to end. From every index start another loop from i to the end of array to get all subarray starting from i, keep a variable sum to calculate the sum. For every index in inner loop update sum = sum + array[j] If the sum is equal to the given sum then print the subarray.
You are trying to solve the Partition Problem; i.e. partition your integers into two subsets, whose sums are the same, and assign positive sign to integers in one subset and negative signs to those in the other subset.
In your particular problem you have a low limit on both the number of integers and the value of those integers. You can apply a standard dynamic algorithm approach with the inclusion/exclusion approach; i.e. finding a subset of the first n
integers that sums to i
, by considering the case where the last of those integers is not used (so you need a subset of the first n-1
integers summing to i
) and where it is used (a subset of the first n-1
integers summing to i - val(n)
).
Here is an idea:
In Java:
// assuming the numbers are positive
// (ignore operator when parsing, line.split("[ +-]+") will do)
public static int canReach0(int[] numbers) {
sort(numbers, 1); // sort(array, offset) doesn't matter what algorithm
// for 300 elements and compared to the complexity of the rest
int[] revSum = new int[numbers.length];
revSum[numbers.length - 1] = numbers[numbers.length - 1];
for (int i = numbers.length - 2; i >= 0; i--)
revSum[i] = revSum[i + 1] + numbers[i];
int sum = numbers[0];
if (sum == revSum[1])
return 0;
return solve(numbers, 1, sum, revSum);
}
private static int solve(int[] numbers, int index, int sum, int[] revSum) {
if (index == numbers.length - 1)
return -1;
int high = sum + numbers[index];
if (high == revSum[index + 1] ||
(high < revSum[index + 1] && solve(numbers, index + 1, high, revSum) == 0))
return 0;
int low = sum - numbers[index];
if (low == -revSum[index + 1] ||
(low > -revSum[index + 1] && solve(numbers, index + 1, low, revSum) == 0))
return 0;
return -1;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With