One Solution:
import java.lang.Math;
...
public int[] solution(int n) {
int[] solution = new int[n];
int targetSum = (n * (n - 1)) / 2;
int runningSum = 0;
double avgRemainder = 0.0;
for (int i = 0; i < n - 1; i++) {
do {
solution[i] = (int)(Math.random() * n);
avgRemainder = (targetSum - runningSum - solution[i])/(n - (i + 1));
if (avgRemainder >= 0.0 && avgRemainder <= (n - 1)) {
runningSum += solution[i];
}
} while (!(avgRemainder >= 0.0 && avgRemainder <= (n - 1)));
}
solution[n - 1] = targetSum - runningSum;
return solution;
}
This will generate a random number, but before adding it to the list of solutions, it will check to see if it will cause the remaining slots to average outside of the range of acceptable numbers, which includes overshooting the target sum.
The cons to this (particularly if order matters) is that it will cause funneling at the end, if you randomly generate large numbers at the beginning, then obviously the remaining numbers will loop until they are small enough to fit in the solution... for example:
If n = 5
If we randomly generate the first two numbers to be 4
[4, 4, ?, ?, ?]
Then this method will loop the 3rd random number until it is between 0 and 2, and if it is 2...
[4, 4, 2, ?, ?]
Then it will loop the remaining numbers until they are 0.
[4, 4, 2, 0, 0]
This should be fine with larger values of n, and it is iterative instead of recursive.
EDIT:
So actually the very last item must be forced because there will only be one solution for solution[n-1]. I fixed the code above to add that because it was getting an: Exception in thread "main" java.lang.ArithmeticException: / by zero.