【问题标题】:Calculate the total amount (number) of combinations of a set with the specified combination length? [duplicate]计算具有指定组合长度的集合的组合的总量(数量)? [复制]
【发布时间】:2017-09-03 13:34:02
【问题描述】:

有一组元素,在本例中是一个由 3 个字符/元素 {A、B、C} 组成的数组:

char[] charSet = "ABC".ToCharArray();

我想编写一个通用的使用函数来帮助确定哪些是可以生成的指定长度的组合总数,并确定有和没有重复的可能组合的数量。为了避免可能的错误:这个问题不是关于组合/烫发的生成,只是计算。

一个简单的未完成的例子来理解我:

public static long CalculateCombinations(int setLength, int comboLength, bool allowRepetition)
{
    return result;
}

( 其中setLength 是集合中元素的数量,comboLength 是每个组合的所需长度,allowRepetition 是一个确定性标志,用于帮助计算何时以及何时不允许元素重复的组合数量在每个组合中。)

然后,如果我有上面指定的相同字符集,并且我想计算重复的可能组合的数量,算法应该返回一个值 9,这将是这一系列组合的等效数量:

1: AA
2: AB
3: AC
4: BA
5: BB
6: BC
7: CA
8: CB
9: CC

如果我不想重复,相同的算法应该返回一个值 6,这将是这一系列组合的等效数量:

1: AB
2: AC
3: BA
4: BC
5: CA
6: CB

基本上,我正在尝试重现此在线服务可以做什么:http://textmechanic.com/text-tools/combination-permutation-tools/combination-generator/ 但是我尝试在 WWW 周围调查和实施不同的“nCr”公式(如 http://www.vcskicks.com/code-snippet/combination.php )和 StackOverflow线程(如https://stackoverflow.com/a/26312275/1248295),但是当计算中涉及组合长度因子和重复时,我不知道如何计算它。也许这可能比我认为的太基础,但数学不是我的强项。

我的问题:我怎样才能编写一个算法来计算我解释的内容?如果有人可以链接公式及其在 C# 或 VB.NET 中的实现,将不胜感激。

【问题讨论】:

  • 正如@Lazar Ljubenović 在他的回答中提到的,这些被称为排列。可以在here 找到非重复版本的一个很好的例子。
  • @Aly El-Haddad 感谢您的评论,但正如我在问题中澄清的那样:“这个问题不是关于组合/排列生成,它只是关于计算。” (即,计算要生成的组合数量的函数。执行此操作所需的公式。)
  • 现在我无法分享回答我自己问题的解决方案,因为一位“版主”决定将我的问题标记为(误报)重复。非常适合 StackOverflow 免费审核概念......每个人都可以无正当理由骚扰他人或误解或仅仅因为不阅读问题可能会给 OP 带来其他问题。

标签: c# .net vb.net math combinations


【解决方案1】:

让我们尝试使用三个字符,ABC (n = 3) 以及 k = 2 的组合长度,如您的示例所述。

有重复

  • 我们从两个空格开始。
  • 第一个空白可以通过 3 种可能的方式填充。
  • 对于三种可能的方式中的每一种,第二个空格可以用另外三种可能的方式填充。

这为您提供了总共3 × 3 个可能性。

一般来说,有n ^ k 的可能性。

不重复

  • 我们从两个空格开始。
  • 第一个空白可以通过 3 种可能的方式填充。
  • 第二个空白区域可以通过 2 种可能的方式填充,因为您不想重复自己。

这为您提供3 × 2 的可能性。

让我们再举一个例子。假设您有五个字母 (ABCDE) 和四个 _ _ _ _ 的组合长度。

  • 我们将五个字母中的任何一个放在第一个空白处。这是五种可能性:A、B、C、D、E。
  • 现在对于最后一步之后的每种可能性,无论我们选择了哪个字母,现在我们都有 4 个字母可供选择。如果在上一步中我们选择了A,那么语料库现在是BCDE——这是四种可能性。对于B,我们从ACDE 中进行选择——这又是一种可能性。总的来说,由于有5 方法可以执行上一步,并且有4 方法可以在任何 之前的选择之后进行,总共有20 可能性:(AB, AC, AD, AE), (BA, BC, BD, BE), (CA, CB, CD, CE), (DA, DB, DC, DE), (EA, EB, EC, ED)。
  • 让我们继续前进。选择两个字母后,我们留下了3。使用与之前相同的逻辑,对于前 20 种可能性中的每一种,我们都有另外 3 种可能性。总共是60
  • 还有一个空间。我们有两个以前没有选择过的字母。从之前的任何60 可能性中,我们现在有两种可能性。总共是 120

所以我们通过乘以 5 × 4 × 3 × 2 得出了这个结论。为什么从5开始?因为我们最初有 5 个字母:ABCDE。为什么我们的乘法中有四个数字?因为有 4 个空格:_ _ _ _

一般情况下,您从n 开始不断乘以一个递减的值,然后执行此操作k 次:n × (n - 1) × ... × (n - k + 1)

最后一个值是(n - k + 1),因为您将k 值相乘。从n(n - k + 1) 总共有k 个值(含)。

我们可以使用 n = 5k = 4 示例对此进行测试。我们说公式是5 × 4 × 3 × 2。现在看一下一般公式:确实,我们从n = 5 开始,不断地相乘,直到得到5 - 4 + 1 = 2


在你的函数签名中,nsetLengthkcomboLength。上述公式的实现应该是微不足道的,所以我把它留给读者。


这些被称为permutations 有和没有重复。

【讨论】:

  • 非常感谢您的回答。重复的解决方案已完成且清晰(非常简单,只需将 n 提升到 k 次方,现在我觉得问这个问题很愚蠢!),但我完全不明白这部分:In general, you keep multiplying with a lower value starting from n, and do this k times: n × (n - 1) × ... × (n - k + 1) 请您添加更多详情?
  • @ElektroStudios 已扩展。希望现在更清楚了。
  • 对不起,我不明白如何在算法中实现逻辑。在您的示例中,如果我有 8 个字母而不是 5 个字母,并且相同的组合长度/空格为 4,则根据您的指示得到的返回值和公式将是 8*4*3*2?,但显然不是(所以我错过了一些东西)。我太老太坏了!。
  • 不,应该是8 * 7 * 6 * 5
  • @ElektroStudios 对我来说看起来不错。虽然我不能说语言使用,但我不使用 C# 或 VB。但是算法看起来不错。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-23
  • 1970-01-01
  • 2022-09-28
相关资源
最近更新 更多