This is an interesting question. It involves more math than programming because only if you discover the math portion then you may implement an efficient algorithm.
However even before getting into the math we must actually understand what exactly the question is. The question can be rephrased as
Given array [1..n]
, find all possible two groups (2 subarrays) with equal sum.
So the rules;
- sum of
[1..n]
is n*n(+1)/2
- If
n*(n+1)/2
is odd then there is no solution.
- If your target sum is
t
then you should not iterate further for lower values than Math.ceil((Math.sqrt(8*t+1)-1)/2)
(by solving n
from n(n+1)/2 = t
equation)
Sorry... I know the question requests Java code but I am not fluent in Java so the code below is in JavaScript. It's good though we can see the results. Also please feel free to edit my answer to include a Java version if you would like to transpile.
So here is the code;
function s2z(n){
function group(t,n){ // (t)arget (n)umber
var e = Math.ceil((Math.sqrt(8*t+1)-1)/2), // don't try after (e)nd
r = [], // (r)esult
d; // (d)ifference
while (n >= e){
d = t-n;
r = d ? r.concat(group(d, d < n ? d : n-1).map(s => s.concat(n)))
: [[n]];
n--;
}
return r;
}
var sum = n*(n+1)/2; // get the sum of series [1..n]
return sum & 1 ? "No solution..!" // if target is odd then no solution
: group(sum/2,n);
}
console.log(JSON.stringify(s2z(7)));
So the result should be [[1,6,7],[2,5,7],[3,4,7],[1,2,4,7],[3,5,6],[1,2,5,6],[1,3,4,6],[2,3,4,5]]
.
what does this mean..? If you look into that carefuly you will notice that
- These are all the possible groups summing up to 14 (half of 28 which is the sum of [1..7].
- The first group (at index
0
) is complemented by the last group (at index length-1
) The second is complemented with the second last and so on...
Now that we have the interim results it's up to us how to display them. This is a secondary and trivial concern. My choice is a simple one as follows.
var arr = [[1,6,7],[2,5,7],[3,4,7],[1,2,4,7],[3,5,6],[1,2,5,6],[1,3,4,6],[2,3,4,5]],
res = arr.reduce((r,s,i,a) => r+s.join("+")+"-"+a[a.length-1-i].join("-")+" = 0 \n","");
console.log(res);
Of course you may put the numbers in an order or might stop halfway preventing the second complements taking positive values while the firsts taking negative values.
This algorithm is not hard tested and i might have overlooked some edges but I believe that this should be a very efficient algorithm. I have calculated up to [1..28]
in a very reasonable time resulting 2399784 uniques groups to be paired. The memory is only allocated for the constructed result set despite this is a resursive approach.