【问题标题】:Permutations without itertools for two values (using recursion!)没有 itertools 的两个值的排列(使用递归!)
【发布时间】:2021-08-01 22:10:29
【问题描述】:

Stackoverflow,我再次寻求您的帮助。

我知道还有其他关于此的主题,但我会解释是什么让我的作业与众不同。

基本上,我的函数会得到一个 0 和 1 的列表,并返回字符串的所有可能顺序。例如对于“0111”,我们将得到“0111”、“1011”、“1101”、“1110”。

这是我的代码:

def permutations(string):
    if len(string) == 1:
        return [string]

    lst = []

    for j in range(len(string)):
        remaining_elements = ''.join([string[i] for i in range(len(string)) if i != j])
        mini_perm = permutations(remaining_elements)

        for perm in mini_perm:
            new_str = string[j] + perm
            if new_str not in lst:
                lst.append(new_str)

    return lst

问题是当我运行像“000000000011”这样的字符串时,需要很长时间来处理。应该有一种更有效的方法来做到这一点,因为它只有两个数字。所以我不应该使用索引?

如果您能找到更有效的说法,请帮助我。

(我可以使用循环,但也必须使用递归!)

【问题讨论】:

  • 您可以随时查看itertools 源代码以了解它是如何实现的,如果您不想使用该模块,请执行类似的操作。 docs.python.org/3/library/itertools.html#itertools.permutations
  • @PacketLoss itertools permutations 函数比我写的自定义版本还要慢,因为它会重复相似的对象。这在基本的 Python 中应该是可能的——递归、for、循环,没有 OOP。
  • 您的示例“000000000011”是否应该返回01 and 10
  • @PacketLoss 它应该返回“000000000011”、“000000000101”、“000000001001”等。

标签: python loops recursion permutation itertools


【解决方案1】:

下面是一个使用更有效的递归创建排列的示例:

def permute(string):
    string = list(string)
    n = len(string)

    # Base conditions
    # If length is 0 or 1, there is only 1 permutation
    if n in [0, 1]:
        return [string]

    # If length is 2, then there are only two permutations
    # Example: [1,2] and [2,1]
    if n == 2:
        return [string, string[::-1]]

    res = []
    # For every number in array, choose 1 number and permute the remaining
    # by calling permute recursively
    for i in range(n):
        permutations = permute(string[:i] + string[i+1:])
        for p in permutations:
            res.append([''.join(str(n) for n in [string[i]] + p)])

    return res

这也适用于permute('000000000011') - 希望对您有所帮助!

【讨论】:

    【解决方案2】:

    您还可以将collections.Counter 与递归生成器函数一起使用:

    from collections import Counter
    def permute(d):
       counts = Counter(d)
       def get_permuations(c, s = []):
         if len(s) == sum(counts.values()):
            yield ''.join(s)
         else:
            for a, b in c.items():
               for i in range(1, b+1):
                  yield from get_permuations({**c, a:b - i}, s+([a]*i))
       return list(set(get_permuations(counts)))
    
    print(permute("0111"))
    print(permute("000000000011"))
    

    输出:

    ['0111', '1110', '1101', '1011']
    ['010000100000', '100000000001', '010000001000', '000000100001', '011000000000', '100000000010', '001001000000', '000000011000', '100000001000', '100000100000', '100001000000', '001000100000', '100010000000', '000000001100', '000100000100', '010010000000', '000000000011', '000000100010', '101000000000', '110000000000', '100000010000', '000100001000', '000001001000', '000000000101', '000000100100', '010000000001', '001000000100', '001000000010', '000110000000', '000011000000', '000001100000', '000000110000', '001000000001', '000010001000', '000100100000', '000001000001', '000010000001', '001100000000', '000100000001', '001000001000', '010000000100', '010000010000', '000000010001', '001000010000', '010001000000', '100000000100', '100100000000', '000000001001', '010100000000', '000010100000', '010000000010', '000000001010', '000010000100', '001010000000', '000000010010', '000001000010', '000100000010', '000101000000', '000000010100', '000100010000', '000000000110', '000001000100', '000010010000', '000000101000', '000001010000', '000010000010']
    

    【讨论】:

      【解决方案3】:

      发布某人给我的答案。感谢您的回复!:

      def permutations(zeroes, ones, lst, perm):
          if zeroes == 0 and ones == 0:
              lst.append(perm)
              return
          elif zeroes < 0 or ones < 0:
              return
          
          permutations(zeroes - 1, ones, lst, perm + '0')
          permutations(zeroes, ones - 1, lst, perm + '1')
      

      【讨论】:

        猜你喜欢
        • 2016-03-04
        • 1970-01-01
        • 2022-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-10
        相关资源
        最近更新 更多