【问题标题】:Recursive Algorithm to generate all permutations of length k of a list in Python在Python中生成列表长度为k的所有排列的递归算法
【发布时间】:2018-09-16 16:21:58
【问题描述】:

我想创建一个递归算法来生成所有排列 具有一定长度的整数列表的指定长度n

以下是我的想法:

对于列表中的每个元素,我可以将其删除,然后让我的递归函数将所有长度为k-1 的排列返回给我,然后将删除的数字添加到每个排列中。然后对列表中的所有数字重复此过程。

基本情况是列表为空或仅包含一个元素。 在这些情况下,我只返回列表。也就是说,只要 k 小于或等于列表的长度(例如,如果 k3,但 l = [1,2],我不能产生任何长度排列 k)。

这是我写的:

def permutations(l, k):
w = len(l)
if (k <= w): # list is bigger than the length each permutations
    if (w <= 1):
        return list(l)
    else:
        result = []
        for element in l:
            listSmaller = l[:element] + l[element+1:]
            for perm in permutations(listSmaller, k-1):
                result.append([perm] + element)
        return result      
else: # list is not bigger than the length of the permutations, impossible.
    print("k cannot exceed length of list")

我不断收到TypeError: can only concatenate list (not "int") to list

我应该如何修改这个?

【问题讨论】:

  • 如果你想从头开始,这将无济于事,但你看过 python itertools 模块吗? docs.python.org/3/library/itertools.html
  • 能否将导致报错的参数提供给permutations?谢谢!
  • 当您使用for element in l: 时,element 不再是从 0 开始的索引,而是列表 l 的各个元素,一次一个。现在,在访问列表 l 的元素时,您不能使用 l[:element]l[element+1:]。您需要一个索引,您可以使用 enumerate as for i, element in enumerate(l): 来获取该索引,然后您可以使用 l[:i] + l[i+1:]
  • 我一直在用 permutations([1,2,3,4], 3) 进行测试
  • 另外,perm 是一个列表,所以你不应该用 [ ] 包裹它。元素是一个 int 所以你应该用 [ ] 包装它(在你追加到结果的行中)

标签: python algorithm recursion permutation


【解决方案1】:
# code takes list lst and int n denoting length of permutation
# returns all permutations of length n over items in lst  
def Perm(lst,n):
    # if length of permutation is negative or 0, return empty
    if n<=0:
        return [[]]
    # else take empty list l 
    l=[]
    # loop over whole lst
    for i in range(0,len(lst)): 
        m=lst[i] # current element of lst (ith) 
        remLst=lst[:i] + lst[i+1:]  # remaining list i.e. all elements except ith
        # recursive call to Perm with remaining list and decremented length 
        for p in Perm(remLst,n-1): 
            # append current element + all sublists p generated through recursion as an item in list l
            l.append([m]+p) 
    return l

# some examples 
# all permutations of length 2 over characters A,B,C
print(Perm(['A','B','C'],2))
# output: [['A', 'B'], ['A', 'C'], ['B', 'A'], ['B', 'C'], ['C', 'A'], ['C', 'B']]

# all permutations of length 2 over characters 1,2,3,4
print(Perm([1,2,3,4],2))
# output: [[1, 2], [1, 3], [1, 4], [2, 1], [2, 3], [2, 4], [3, 1], [3, 2], [3, 4], [4, 1], [4, 2], [4, 3]]

【讨论】:

  • 虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。
【解决方案2】:

有两个问题:

首先[perm] + element 在这里您将列表添加到整数。

第二listSmaller = l[:element] + l[element+1:] 这里需要一个索引来访问列表的元素。您当前正在使用元素作为索引,因此将获得 IndexError,因为当 element=4 时,element+1 将是 5,但您没有 l[4+1:]


当我对您的代码进行以下更改时,您的代码将起作用。我只显示修改后的行。我不确定输出是否符合预期。你可以试试,告诉我。

for i, element in enumerate(l):
    listSmaller = l[:i] + l[i+1:]

    for perm in permutations(listSmaller, k-1):
        result.append([perm] + [element])

【讨论】:

    【解决方案3】:

    在python中,使用时

    for a in b:
    

    'a' 实际上不是一个可以用作索引的数字,而是指向列表'b' 中实际元素的指针。换句话说,如果我有以下列表

    b = ["Bob", "Jim", "Jane"]
    

    那么在第一次迭代中,“a”将等于“Bob”,而不是 0。

    当你想生成索引号而不是指向元素的指针时,你可以使用:

    for a in range(0, len(b)):
    

    相反。使用它,您的代码应该可以工作。

    例如

    for element in range(0, len(l)):
        listSmaller = l[:element] + l[element+1:]
        for perm in permutations(listSmaller, k-1):
            result.append([perm] + element)
    return result
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-02
      • 2012-05-05
      • 2019-03-26
      • 2012-01-30
      • 1970-01-01
      • 1970-01-01
      • 2020-08-18
      相关资源
      最近更新 更多