Reputation: 65
I have this function
public int numberOfPossiblePairs(int n)
{
int k=2;
if (k>n-k) { k=n-k;}
int b=1;
for (int i=1, m=n; i<=k; i++, m--)
b=b*m/i;
return b;
}
Which gets the number of pairs you can make from given number of items, so for example, if you have an array of 1000 items, you can make 499,500 pairs. But what I actually need is the opposite. In other words a function that would take 499500 as the parameter, and return 1000 as the original number of unique items that could produce that many pairs. (Would be a bonus if it could also handle imperfect numbers, like 499501, of which there is no number of unique items that makes exactly that many unique pairs, but it would still return 1000 as the closest since it produces 499500 pairs.)
I realize I could just incrementally loop numberOfPossiblePairs() until I see the number I am looking for, but seems like there should be an algorithmic way of doing this rather than brute forcing it like that.
Upvotes: 1
Views: 564
Reputation: 7597
Your problem boils down to a little algebra and can be solved in O(1)
time. We first note that your function does not give the number of permutations of pairs, but rather the number of combinations of pairs. At any rate the logic that follows can be easily altered to accommodate permutations.
We start off by writing the formula for number of combinations choose k.
Setting n = 1000 and r = 2 gives:
1000! / (2!(998)!) = 1000 * 999 / 2 = 499500
Just as numberOfPossiblePairs(1000)
does.
Moving on in our exercise, for our example we have r = 2, thus:
total = n! / ((n - 2)! * 2!)
We now simplify:
total = (n * (n - 1)) / 2
total * 2 = n^2 - n
n^2 - n - 2 * total = 0
Now we can apply the quadratic formula to solve for n.
Here we have x = n, a = 1, b = -1, and c = -2 * total which give:
n = (-(-1) +/- sqrt(1^2 - 4 * 1 * (-2 * total))) / 2
Since we are only interested in positive numbers we exclude the negative solution. In code we have something like (Note, it looks like the OP is using Java and I am not an expert here... the following is C++
):
int originalNumber(int total) {
int result;
result = (1 + std::sqrt(1 - 4 * 1 * (-2 * total))) / 2;
return result;
}
As for the bonus question of returning the closest value if the result isn't a whole number, we could simply round the result before coercing to an integer:
int originalNumber(int total) {
int result;
double temp;
temp = (1 + std::sqrt(1 - 4 * 1 * (-2 * total))) / 2;
result = (int) std::round(temp);
return result;
}
Now when values like 500050
are passed, the actual result is 1000.55
, and the above would return 1001
, whereas the first solution would return 1000
.
Upvotes: 1