获得具有松散条件的一组元素的第N个组合

时间:2018-04-21 11:36:28

标签: math permutation combinatorics

假设:

  1. 尺寸为M
  2. 的符号列表
  3. 组合L的期望大小
  4. 符号可能会在组合中出现任意次数
  5. 任何符号组合的所有排列都必须记入帐户
  6. 示例:对于符号列表(a, b, c)和L = 4,所有组合(a, a, a, a)(a, b, a, c)(a, c, b, b)等都有效。由于缺乏一个更好的术语,我称这是松散的组合"。

    组合的特定顺序并不重要。给定组合索引N,算法应从满足条件的一组可能组合返回唯一组合。我的猜测是,如果我们将组合视为基数M和长度L的数字,那么最自然的顺序是这样,因此正常的数字顺序将适用,但这不是必须遵循的。

    找到第N个组合的算法是什么?

    我不确定如何自己找到答案,并且一直在寻找其他地方是否有针对这一特定条件的答案,但没有找到答案。我找到的所有问题对重复元素(如(a, a, b, b))和重新排列顺序组合(如(a, a, b, c)(a, b, c, a)(a, c, a, b)的组合不感兴趣)被视为相同的组合

1 个答案:

答案 0 :(得分:2)

正如你已经想到的那样,你基本上有兴趣枚举基数为M的长度数。 因此,解决方案可能如下所示:

  • 定义双射{0,...,M-1} - >符号,即枚举符号。
  • 对于任何非负整数N < M ^ L,确定其基本M表示。
    • 通过重复模M和M舍入分割轻松完成。
    • 不失一般性,通过根据需要添加前导零来获得长度M.
  • 使用您的双射将此数字0到M-1的列表转换为松散的符号组合。

所以,让我们详细介绍这一部分:

  

通过重复模数M和向下舍入M来轻松完成。

伪代码:

int a[L];
for int i from 0 to L-1 do
    a[i] = N % M; // Should go from 0 to M-1
    N = N / M; // Rounded down, of course
done