def permutations (orig_list):if not isinstance(orig_list, list):orig_list = list(orig_list)
yield orig_list
if len(orig_list) == 1:return
for n in sorted(orig_list):new_list = orig_list[:]pos = new_list.index(n)del(new_list[pos])new_list.insert(0, n)for resto in permutations(new_list[1:]):if new_list[:1] + resto <> orig_list:yield new_list[:1] + resto
def permutations(elements):if len(elements) <= 1:yield elementsreturnfor perm in permutations(elements[1:]):for i in range(len(elements)):# nb elements[0:1] works in both string and list contextsyield perm[:i] + elements[0:1] + perm[i:]
itertools.permutations的留档中列出了几种替代方法。这里有一个:
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 210pool = tuple(iterable)n = len(pool)r = n if r is None else rif r > n:returnindices = 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] -= 1if cycles[i] == 0:indices[i:] = indices[i+1:] + indices[i:i+1]cycles[i] = n - ielse:j = cycles[i]indices[i], indices[-j] = indices[-j], indices[i]yield tuple(pool[i] for i in indices[:r])breakelse:return
另一个,基于itertools.product:
def permutations(iterable, r=None):pool = tuple(iterable)n = len(pool)r = n if r is None else rfor indices in product(range(n), repeat=r):if len(set(indices)) == r:yield tuple(pool[i] for i in indices)
def permute_in_place(a):a.sort()yield list(a)
if len(a) <= 1:return
first = 0last = len(a)while 1:i = last - 1
while 1:i = i - 1if a[i] < a[i+1]:j = last - 1while not (a[i] < a[j]):j = j - 1a[i], a[j] = a[j], a[i] # swap the valuesr = a[i+1:last]r.reverse()a[i+1:last] = ryield list(a)breakif i == first:a.reverse()return
if __name__ == '__main__':for n in range(5):for a in permute_in_place(range(1, n+1)):print aprint
for a in permute_in_place([0, 0, 1, 1, 1]):print aprint
list2Perm = [1, 2.0, 'three']listPerm = [[a, b, c]for a in list2Permfor b in list2Permfor c in list2Permif ( a != b and b != c and a != c )]print listPerm
def all_perms(elements):if len(elements) <= 1:yield elements # Only permutation possible = no permutationelse:# Iteration over the first element in the result permutation:for (index, first_elmt) in enumerate(elements):other_elmts = elements[:index]+elements[index+1:]for permutation in all_perms(other_elmts):yield [first_elmt] + permutation
global resultresult = []
def permutation(li):if li == [] or li == None:return
if len(li) == 1:result.append(li[0])print resultresult.pop()return
for i in range(0,len(li)):result.append(li[i])permutation(li[:i] + li[i+1:])result.pop()
from __future__ import print_function
def perm(n):p = []for i in range(0,n+1):p.append(i)while True:for i in range(1,n+1):print(p[i], end=' ')print("")i = n - 1found = 0while (not found and i>0):if p[i]<p[i+1]:found = 1else:i = i - 1k = nwhile p[i]>p[k]:k = k - 1aux = p[i]p[i] = p[k]p[k] = auxfor j in range(1,(n-i)/2+1):aux = p[i+j]p[i+j] = p[n-j+1]p[n-j+1] = auxif not found:break
perm(5)
def addperm(x,l):return [ l[0:i] + [x] + l[i:] for i in range(len(l)+1) ]
def perm(l):if len(l) == 0:return [[]]return [x for y in perm(l[1:]) for x in addperm(l[0],y) ]
print perm([ i for i in range(3)])
def permute(xs, low=0):if low + 1 >= len(xs):yield xselse:for p in permute(xs, low + 1):yield pfor i in range(low + 1, len(xs)):xs[low], xs[i] = xs[i], xs[low]for p in permute(xs, low + 1):yield pxs[low], xs[i] = xs[i], xs[low]
for p in permute([1, 2, 3, 4]):print p
from math import factorialdef permutations(l):permutations=[]length=len(l)for x in xrange(factorial(length)):available=list(l)newPermutation=[]for radix in xrange(length, 0, -1):placeValue=factorial(radix-1)index=x/placeValuenewPermutation.append(available.pop(index))x-=index*placeValuepermutations.append(newPermutation)return permutations
permutations(range(3))
def permutation(list):if len(list) == 0:return [[]]else:return [[x] + ys for x in list for ys in permutation(delete(list, x))]
def delete(list, item):lc = list[:]lc.remove(item)return lc
def permute(items):length = len(items)def inner(ix=[]):do_yield = len(ix) == length - 1for i in range(0, length):if i in ix: #avoid duplicatescontinueif do_yield:yield tuple([items[y] for y in ix + [i]])else:for p in inner(ix + [i]):yield preturn inner()
用法:
for p in permute((1,2,3)):print(p)
(1, 2, 3)(1, 3, 2)(2, 1, 3)(2, 3, 1)(3, 1, 2)(3, 2, 1)
def pzip(c, seq):result = []for item in seq:for i in range(len(item)+1):result.append(item[i:]+c+item[:i])return result
def perm(line):seq = [c for c in line]if len(seq) <=1 :return seqelse:return pzip(seq[0], perm(seq[1:]))
In [1]: %timeit -n10 list(permutations(range(10)))10 loops, best of 3: 815 ms per loop
In [2]: %timeit -n100 perms(10)100 loops, best of 3: 40 ms per loop
def calcperm(arr, size):result = set([()])for dummy_idx in range(size):temp = set()for dummy_lst in result:for dummy_outcome in arr:if dummy_outcome not in dummy_lst:new_seq = list(dummy_lst)new_seq.append(dummy_outcome)temp.add(tuple(new_seq))result = tempreturn result
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 stringsdef permutations(input):return permutes( list(input), 0 )
# Main Programprint( permutations("wxyz") )
@numba.njit()def permutations(A, k):r = [[i for i in range(0)]]for i in range(k):r = [[a] + b for a in A for b in r if (a in b)==False]return rpermutations([1,2,3],3)[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
给人留下关于性能的印象:
%timeit permutations(np.arange(5),5)
243 µs ± 11.1 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)time: 406 ms
%timeit list(itertools.permutations(np.arange(5),5))15.9 µs ± 8.61 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)time: 12.9 s
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 = resultreturn anspermutations([1, 2, 2])> [[1, 2, 2], [2, 1, 2], [2, 2, 1]]
def permutation(input):if len(input) == 1:return input if isinstance(input, list) else [input]
result = []for i in range(len(input)):first = input[i]rest = input[:i] + input[i + 1:]rest_permutation = permutation(rest)for p in rest_permutation:result.append(first + p)return result
def getPermutations(array):if len(array) == 1:return [array]permutations = []for i in range(len(array)):# get all perm's of subarray w/o current itemperms = getPermutations(array[:i] + array[i+1:])for p in perms:permutations.append([array[i], *p])return permutations
产量实现:
def getPermutations(array):if len(array) == 1:yield arrayelse:for i in range(len(array)):perms = getPermutations(array[:i] + array[i+1:])for p in perms:yield [array[i], *p]
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
from typing import Listimport 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_timedef _permute_recur(self, nums: List[int], l: int, r: int, perms: List[List[int]]):# base caseif 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_timedef _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)```
'''Lexicographic permutation generation
consider example array state of [1,5,6,4,3,2] for sorted [1,2,3,4,5,6]after 56432(treat as number) ->nothing larger than 6432(using 6,4,3,2) beginning with 5so 6 is next larger and 2345(least using numbers other than 6)so [1, 6,2,3,4,5]'''def hasNextPermutation(array, len):' Base Condition 'if(len ==1):return False'''Set j = last-2 and find first j such that a[j] < a[j+1]If no such j(j==-1) then we have visited all permutationsafter this step a[j+1]>=..>=a[len-1] and a[j]<a[j+1]
a[j]=5 or j=1, 6>5>4>3>2'''j = len -2while (j >= 0 and array[j] >= array[j + 1]):j= j-1if(j==-1):return False# print(f"After step 2 for j {j} {array}")'''decrease l (from n-1 to j) repeatedly until a[j]<a[l]Then swap a[j], a[l]a[l] is the smallest element > a[j] that can follow a[l]...a[j-1] in permutationbefore swap we have a[j+1]>=..>=a[l-1]>=a[l]>a[j]>=a[l+1]>=..>=a[len-1]after swap -> a[j+1]>=..>=a[l-1]>=a[j]>a[l]>=a[l+1]>=..>=a[len-1]
a[l]=6 or l=2, j=1 just before swap [1, 5, 6, 4, 3, 2]after swap [1, 6, 5, 4, 3, 2] a[l]=5, a[j]=6'''l = len -1while(array[j] >= array[l]):l = l-1# print(f"After step 3 for l={l}, j={j} before swap {array}")array[j], array[l] = array[l], array[j]# print(f"After step 3 for l={l} j={j} after swap {array}")'''Reverse a[j+1...len-1](both inclusive)
after reversing [1, 6, 2, 3, 4, 5]'''array[j+1:len] = reversed(array[j+1:len])# print(f"After step 4 reversing {array}")return True
array = [1,2,4,4,5]array.sort()len = len(array)count =1print(array)'''The algorithm visits every permutation in lexicographic ordergenerating one by one'''while(hasNextPermutation(array, len)):print(array)count = count +1# The number of permutations will be n! if no duplicates are present, else less than that# [1,4,3,3,2] -> 5!/2!=60print(f"Number of permutations: {count}")
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