从可能的对数中获取原始数组的大小

时间:2018-07-30 14:57:48

标签: combinations

我有这个功能

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()直到看到所需的数字,但似乎应该有一种算法来做到这一点,而不是像这样强行强迫它。

1 个答案:

答案 0 :(得分:1)

您的问题可以归结为一点代数,可以在O(1)时间内解决。首先我们要注意的是,您的函数并没有给出对的排列数量,而是给出了对的组合数量。无论如何,可以轻松更改以下逻辑以适应排列。

我们首先编写组合数量的公式,选择 k

enter image description here

设置 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

enter image description here

这里我们有 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