【问题标题】:Algorithm for combination index in array数组中组合索引的算法
【发布时间】:2016-06-11 13:42:39
【问题描述】:

我知道如何计算给定 n 和 k 的 binomial coefficient(我为此使用了一个库)。 现在假设您将所有这些组合存储在一个数组中。每个组合都有一个索引。我实际上不需要将它们存储在数组中,但我需要知道,如果要存储它们,每个组合的数组索引是多少。

例如给定可能组合的 C(n,k) 集合中的一个元素,我需要一个函数,它可以在数组中给出它的索引 i,而实际上并不创建整个数组。编程语言无所谓,虽然我需要在java中实现功能,但是任何(伪)语言算法都可以,然后我将它翻译成java。

例如在n=5和k=2的情况下,我凭经验定义这个函数f(n, k, [a,b]) => N为:

f(5, 2, [1,2]) = 0
f(5, 2, [1,3]) = 1
f(5, 2, [1,4]) = 2
f(5, 2, [1,5]) = 3
f(5, 2, [2,3]) = 4
f(5, 2, [2,4]) = 5
f(5, 2, [2,5]) = 6
f(5, 2, [3,4]) = 7
f(5, 2, [3,5]) = 8
f(5, 2, [4,5]) = 9

表示 (3,5) 组合将占用数组中的索引 8。另一个 n=5 和 k=3 的例子是f(n, k, [a,b,c]) => N,根据经验定义为

f(5, 3, [1,2,3]) = 0
f(5, 3, [1,2,4]) = 1
f(5, 3, [1,2,5]) = 2
f(5, 3, [1,3,4]) = 3
f(5, 3, [1,3,5]) = 4
f(5, 3, [1,4,5]) = 5
f(5, 3, [2,3,4]) = 6
f(5, 3, [2,3,5]) = 7
f(5, 3, [2,4,5]) = 8
f(5, 3, [3,4,5]) = 9

在 cmets 之后进行澄清:

在上面的例子中,[1,2,3]、[2,4,5] 等是 C(n,k) 集合的元素之一,例如n 个可能数中 k 个数的可能组合之一。该函数需要它们来计算它们在数组中的索引。

但是,我需要为 n 和 k 的通用值编写此函数,而无需创建数组。也许这样的函数已经存在于一些组合微积分库中,但我什至不知道它会被如何调用。

【问题讨论】:

  • 提示:数组元素个数为(n*(n-1)) /2
  • @wildplasser 不,恐怕不是。数组中元素的数量是 n 和 k 的二项式系数,例如n!/(k!(n-k)!)
  • 你说的是数组的内容。我说的是数组的 size (:= 元素数),在你的情况下 (5*4/2) 是 10。
  • 不,我也在谈论数组大小。 5*2 也是 10,但这并不意味着正确的函数是 n*k。
  • Hint2:索引是元素之前的数量。 (假设基数为零索引)

标签: algorithm combinations


【解决方案1】:

您应该查看combinatorial number system,尤其是“排序中的组合位置”部分。

甚至还有一个可能对您有所帮助的示例:National Lottery example in Excel。 (对不起,我不能在这里输入任何数学。)

在你的情况下,这将是

f(5, 3, [2,3,4]) = binom(5,3) - 1 - binom(5-2,3) - binom(5-3,2) - binom(5-4,1) =
                 = 10 - 1 - 1 - 1 - 1 = 6

或者如果您接受相反的顺序,您可以省略binom(5,3) - 1 部分并计算

f'(5, 3, [2,3,4]) = binom(5-2,3) + binom(5-3,2) + binom(5-4,1) - 1 =
                  = 1 + 1 + 1 - 1 = 2

(这应该可以为您节省一些时间,因为binom(5, 3) 在这里并不是真正需要的。)

在 Java 中,该方法可以是

int f(int n, int k, int[] vars) {
    int res = binom(n, k) - 1;

    for(int i = 0; i < k; i++) {
        res -= binom(n - vars[i], k - i);
    }

    return res;
}

int fPrime(int n, int k, int[] vars) {
    int res = -1;

    for(int i = 0; i < k; i++) {
        res += binom(n - vars[i], k - i);
    }

    return res;
}

假设int binom(int n, int k)binom(n, k) = 0n &lt; k 的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-18
    • 2014-01-12
    • 1970-01-01
    相关资源
    最近更新 更多