我有这个功能
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;
}
从给定数量的项目中可以获得多少对,因此,例如,如果有1000个项目的数组,则可以使499,500对。但是我真正需要的是相反的。换句话说,该函数将以499500作为参数,并返回1000作为可以产生这么多对的唯一项的原始数量。 (如果它还可以处理不完美的数字(如499501),这将是一个额外的奖励,其中不存在数量众多的唯一项,它们恰好具有如此多的唯一对,但由于它产生499500对,它仍将返回1000作为最接近的对。) / p>
我意识到我可以递增循环遍历numberOfPossiblePairs()直到看到所需的数字,但似乎应该有一种算法来做到这一点,而不是像这样强行强迫它。
答案 0 :(得分:1)
您的问题可以归结为一点代数,可以在O(1)
时间内解决。首先我们要注意的是,您的函数并没有给出对的排列数量,而是给出了对的组合数量。无论如何,可以轻松更改以下逻辑以适应排列。
我们首先编写组合数量的公式,选择 k 。
设置 n = 1000 和 r = 2 给出:
1000! / (2!(998)!) = 1000 * 999 / 2 = 499500
就像numberOfPossiblePairs(1000)
一样。
继续进行练习,对于我们的示例,我们有 r = 2 ,因此:
total = n! / ((n - 2)! * 2!)
我们现在简化:
total = (n * (n - 1)) / 2
total * 2 = n^2 - n
n^2 - n - 2 * total = 0
现在,我们可以应用二次公式来求解 n 。
这里我们有 x = n , a = 1 , b = -1 和 c = -2 *总计给出:
n = (-(-1) +/- sqrt(1^2 - 4 * 1 * (-2 * total))) / 2
由于我们只对正数感兴趣,因此我们排除了负解。在代码中,我们有类似的内容(请注意,好像OP正在使用Java,而我不是这里的专家……下面是C++
):
int originalNumber(int total) {
int result;
result = (1 + std::sqrt(1 - 4 * 1 * (-2 * total))) / 2;
return result;
}
关于如果结果不是整数则返回最接近值的奖励问题,我们可以在将结果强制为整数之前将结果四舍五入
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;
}
现在,当传递诸如500050
之类的值时,实际结果为1000.55
,上面的结果将返回1001
,而第一个解决方案将返回1000
。