【问题标题】:Finding the different combinations [closed]寻找不同的组合[关闭]
【发布时间】:2012-10-03 07:38:46
【问题描述】:

你如何找到一个 40 个字母的字符串的所有组合?

我必须找出 20 D 和 20 R 可以组成多少个组合。

在一个组合中可能是......

DDDDDDDDDDDDDDDDDDDDRRRRRRRRRRRRRRRRRRRR

这是 1 个组合,现在我该如何计算其余的?

【问题讨论】:

  • 您能否澄清一下,您是想实际生成所有组合还是只知道有多少个独特组合? (一个答案涉及 itertools;另一个是基础数学)
  • 这可能属于math.stackexchange.com
  • 那么...您确定要组合而不是排列吗?
  • 我建议 math.stackexchange.com 的原因是您说您想要答案以及如何获得它。使用数学来做到这一点比构建所有选项更有效。或者,研究直接公式的排列和组合。
  • 我感觉这里的一些答案会让你得到错误的答案,因为你可能想要独特的排列,这不是 itertools 会给你的;但是你会在这里找到答案:stackoverflow.com/questions/6284396/…

标签: python


【解决方案1】:

计算20个D和20个R的每一个组合,我们可以认为有40个“槽”,其中20个将由D填充,其余的将由@987654325填充@。所以,我们可以用C(40, 20)计算combinations的总数,或者40选20,可以用下面的公式表示:

40!/(20!*(40-20)!)

或者在 Python 中:

>>> import math
>>> math.factorial(40) / (math.factorial(20) * math.factorial(40-20))
137846528820L

请注意,这与具有 20 个 D 和 20 个 R 的字符串的 unique 排列数相同,但如果您只计算该字符串的排列数您将计算很多重复项,如果您尝试通过创建每个排列来计算这一点,则需要很长时间。

如果您想实际生成唯一的排列(我不建议这样做),一种方法是使用itertools.combinations(range(40), 20)。此处返回的每个元素都是 20 个整数的元组,这将是该特定排列中每个 D 的索引。

【讨论】:

    【解决方案2】:

    有很多排列。仅仅为了计算它们而生成它们通常不是一个好主意。您应该寻找一个数学公式来解决这个问题,或者使用动态规划来计算结果。

    【讨论】:

      【解决方案3】:

      这是一个内置在 itertools 中的不错的函数:

      直接取自此链接:9.7. itertools — Functions creating iterators for efficient looping

      def permutations(iterable, r=None):
          # permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC
          # permutations(range(3)) --> 012 021 102 120 201 210
          pool = tuple(iterable)
          n = len(pool)
          r = n if r is None else r
          if r > n:
              return
          indices = range(n)
          cycles = range(n, n-r, -1)
          yield tuple(pool[i] for i in indices[:r])
          while n:
              for i in reversed(range(r)):
                  cycles[i] -= 1
                  if cycles[i] == 0:
                      indices[i:] = indices[i+1:] + indices[i:i+1]
                      cycles[i] = n - i
                  else:
                      j = cycles[i]
                      indices[i], indices[-j] = indices[-j], indices[i]
                      yield tuple(pool[i] for i in indices[:r])
                      break
              else:
                  return
      

      编辑

      我已经包含了我在 SO 上找到的一个链接,它提供了一个使用 JavaScript 执行此操作的很好的示例:Is there any pre-built method for finding all permutations of a given string in JavaScript?

      如果您不介意 PHP,以下是直接取自此链接的示例:4.26. Finding All Permutations of an Array

      注意:要使用pc_permute 函数,您需要将字符串分成一个字符数组。

      function pc_permute($items, $perms = array( )) {
          if (empty($items)) { 
              print join(' ', $perms) . "\n";
          }  else {
              for ($i = count($items) - 1; $i >= 0; --$i) {
                   $newitems = $items;
                   $newperms = $perms;
                   list($foo) = array_splice($newitems, $i, 1);
                   array_unshift($newperms, $foo);
                   pc_permute($newitems, $newperms);
               }
          }
      }
      

      【讨论】:

      • 你最后的答案是 js 吗?我本可以使用它。
      • 实际上是在 PHP 中(我看错了)。但是,如果你想要 JavaScript,here is a link I found on SO 我相信会有所帮助。
      • 我真的不介意什么语言 xD
      • 更新了答案以包括 JavaScript 参考以及 PHP 示例。
      • 排列的数量会很大吗?
      【解决方案4】:

      根据您想对组合做什么,有很多方法可以解决这个问题。如果您只想知道存在的组合/排列的数量,数学可以告诉您。

      如果您想做一些事情,比如构建一个蛮力算法来检查给定字符集的所有可能排列,itertools.product() 可以提供帮助。

      http://docs.python.org/library/itertools.html#module-itertools

      【讨论】:

        【解决方案5】:

        这是一个生成所有不同排列的生成器。

        def distinct_pem(A,D):
            if A==0: yield 'D'*D
            elif D==0: yield 'A'*A
            elif A==1 and D==1:
                yield 'AD'
                yield 'DA'
            else:
                if A>=2:
                    for string in distinct_pem(A-2,D):
                        yield  'AA'+string
                if A>1 and D>1:
                    for string in distinct_pem(A-1,D-1):
                        yield  'AD'+string
                        yield  'DA'+string
                if D>=2:
                    for string in distinct_pem(A,D-2):
                        yield  'DD'+string
        

        对于 10 个来说,这非常快,但对于 20 个来说却很困难(也许它可以变得更高效?)。

        【讨论】:

          猜你喜欢
          • 2010-12-05
          • 1970-01-01
          • 2010-09-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-09-29
          • 2010-10-07
          • 2012-01-08
          相关资源
          最近更新 更多