【问题标题】:How to generate all permutations of a list?如何生成列表的所有排列?
【发布时间】:2010-09-11 09:22:30
【问题描述】:

如何在 Python 中生成列表的所有排列,而与列表中元素的类型无关?

例如:

permutations([])
[]

permutations([1])
[1]

permutations([1, 2])
[1, 2]
[2, 1]

permutations([1, 2, 3])
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]

【问题讨论】:

  • 我同意递归,接受的答案 - 今天。然而,这仍然是一个巨大的计算机科学问题。公认的答案以指数复杂度解决了这个问题 (2^N N=len(list)) 在多项式时间内解决它(或证明你不能):) 请参阅“旅行推销员问题”
  • @FlipMcF 很难在多项式时间内“解决”它,因为它需要阶乘时间来枚举输出......所以,不,这是不可能的。
  • @FlipMcF: 不,这不是真的:a) 只是为了找到 最佳 解决方案,而不是 足够好 解决方案,这对于现实世界的目的和b)我们不需要扩展搜索空间中的所有节点,即所有排列;这就是heuristic algorithms like A*

标签: python algorithm permutation combinatorics python-2.5


【解决方案1】:
def permutate(l):
    for i, x in enumerate(l):
        for y in l[i + 1:]:
            yield x, y


if __name__ == '__main__':
    print(list(permutate(list('abcd'))))
    print(list(permutate([1, 2, 3, 4])))

#[('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd')]
#[(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]

【讨论】:

  • 美观又简单!
【解决方案2】:

我的 Python 解决方案:

def permutes(input,offset):
    if( len(input) == offset ):
        return [''.join(input)]

    result=[]        
    for i in range( offset, len(input) ):
         input[offset], input[i] = input[i], input[offset]
         result = result + permutes(input,offset+1)
         input[offset], input[i] = input[i], input[offset]
    return result

# input is a "string"
# return value is a list of strings
def permutations(input):
    return permutes( list(input), 0 )

# Main Program
print( permutations("wxyz") )

【讨论】:

    【解决方案3】:
    def permutation(word, first_char=None):
        if word == None or len(word) == 0: return []
        if len(word) == 1: return [word]
    
        result = []
        first_char = word[0]
        for sub_word in permutation(word[1:], first_char):
            result += insert(first_char, sub_word)
        return sorted(result)
    
    def insert(ch, sub_word):
        arr = [ch + sub_word]
        for i in range(len(sub_word)):
            arr.append(sub_word[i:] + ch + sub_word[:i])
        return arr
    
    
    assert permutation(None) == []
    assert permutation('') == []
    assert permutation('1')  == ['1']
    assert permutation('12') == ['12', '21']
    
    print permutation('abc')
    

    输出:['abc', 'acb', 'bac', 'bca', 'cab', 'cba']

    【讨论】:

      【解决方案4】:

      使用Counter

      from collections import Counter
      
      def permutations(nums):
          ans = [[]]
          cache = Counter(nums)
      
          for idx, x in enumerate(nums):
              result = []
              for items in ans:
                  cache1 = Counter(items)
                  for id, n in enumerate(nums):
                      if cache[n] != cache1[n] and items + [n] not in result:
                          result.append(items + [n])
      
              ans = result
          return ans
      permutations([1, 2, 2])
      > [[1, 2, 2], [2, 1, 2], [2, 2, 1]]
      
      

      【讨论】:

        【解决方案5】:
        def permuteArray (arr):
        
            arraySize = len(arr)
        
            permutedList = []
        
            if arraySize == 1:
                return [arr]
        
            i = 0
        
            for item in arr:
        
                for elem in permuteArray(arr[:i] + arr[i + 1:]):
                    permutedList.append([item] + elem)
        
                i = i + 1    
        
            return permutedList
        

        我不打算在新产品线中穷尽所有可能性,以使其有些独特。

        【讨论】:

          【解决方案6】:
          from typing import List
          import time, random
          
          def measure_time(func):
              def wrapper_time(*args, **kwargs):
                  start_time = time.perf_counter()
                  res = func(*args, **kwargs)
                  end_time = time.perf_counter()
                  return res, end_time - start_time
          
              return wrapper_time
          
          
          class Solution:
              def permute(self, nums: List[int], method: int = 1) -> List[List[int]]:
                  perms = []
                  perm = []
                  if method == 1:
                      _, time_perm = self._permute_recur(nums, 0, len(nums) - 1, perms)
                  elif method == 2:
                      _, time_perm = self._permute_recur_agian(nums, perm, perms)
                      print(perm)
                  return perms, time_perm
          
              @measure_time
              def _permute_recur(self, nums: List[int], l: int, r: int, perms: List[List[int]]):
                  # base case
                  if l == r:
                      perms.append(nums.copy())
          
                  for i in range(l, r + 1):
                      nums[l], nums[i] = nums[i], nums[l]
                      self._permute_recur(nums, l + 1, r , perms)
                      nums[l], nums[i] = nums[i], nums[l]
          
              @measure_time
              def _permute_recur_agian(self, nums: List[int], perm: List[int], perms_list: List[List[int]]):
                  """
                  The idea is similar to nestedForLoops visualized as a recursion tree.
                  """
                  if nums:
                      for i in range(len(nums)):
                          # perm.append(nums[i])  mistake, perm will be filled with all nums's elements.
                          # Method1 perm_copy = copy.deepcopy(perm)
                          # Method2 add in the parameter list using + (not in place)
                          # caveat: list.append is in-place , which is useful for operating on global element perms_list
                          # Note that:
                          # perms_list pass by reference. shallow copy
                          # perm + [nums[i]] pass by value instead of reference.
                          self._permute_recur_agian(nums[:i] + nums[i+1:], perm + [nums[i]], perms_list)
                  else:
                      # Arrive at the last loop, i.e. leaf of the recursion tree.
                      perms_list.append(perm)
          
          
          
          if __name__ == "__main__":
              array = [random.randint(-10, 10) for _ in range(3)]
              sol = Solution()
              # perms, time_perm = sol.permute(array, 1)
              perms2, time_perm2 = sol.permute(array, 2)
              print(perms2)
              # print(perms, perms2)
              # print(time_perm, time_perm2)
          ```
          

          【讨论】:

          • 一些解释会改善这个答案。
          【解决方案7】:

          如果有人喜欢这种丑陋的单线(虽然仅适用于字符串):

          def p(a):
              return a if len(a) == 1 else [[a[i], *j] for i in range(len(a)) for j in p(a[:i] + a[i + 1:])]
          

          【讨论】:

            【解决方案8】:

            使用递归求解,遍历元素,获取第 i 个元素,然后问自己:'其余元素的排列是什么',直到没有元素为止。

            我在这里解释了解决方案:https://www.youtube.com/watch?v=_7GE7psS2b4

            class Solution:
                def permute(self,nums:List[int])->List[List[int]]:
                    res=[]
                    def dfs(nums,path):
                        if len(nums)==0:
                            res.append(path)
                        for i in range(len(nums)):
                            dfs(nums[:i]+nums[i+1:],path+[nums[i]])
                    dfs(nums,[])
                    return res
            

            【讨论】:

              【解决方案9】:

              对于 Python,我们可以使用 itertools 并导入排列和组合来解决您的问题

              from itertools import product, permutations
              A = ([1,2,3])
              print (list(permutations(sorted(A),2)))
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2023-03-04
                • 2019-04-24
                • 1970-01-01
                • 2012-05-05
                • 1970-01-01
                • 1970-01-01
                • 2013-11-09
                相关资源
                最近更新 更多