목록의 모든 순열을 생성하는 방법은 무엇입니까?


592

목록의 요소 유형에 관계없이 파이썬에서 목록의 모든 순열을 어떻게 생성합니까?

예를 들면 다음과 같습니다.

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]

5
나는 재귀적이고 받아 들여진 대답에 동의합니다-오늘. 그러나 이것은 여전히 ​​거대한 컴퓨터 과학 문제로 남아 있습니다. 받아 들여진 대답은 지수 복잡성 으로이 문제를 해결합니다 (2 ^ NN = len (list)) 다항식 시간에 해결 (또는 증명할 수 없음) :) "여행사 문제 여행"참조
— FlipMcF

37
@FlipMcF 출력을 열거하는 데에도 시간이 걸리므로 다항식 시간으로 "해결"하기가 어려울 수 있습니다. 따라서 불가능합니다.
— Thomas

답변:


488

Python 2.6부터 (그리고 Python 3을 사용하는 경우)이를위한 표준 라이브러리 도구가 itertools.permutations있습니다.

import itertools
list(itertools.permutations([1, 2, 3]))

당신이 사용하는 경우 이전의 파이썬 (<2.6) 작동 방법을 알고 어떤 이유로 아니면 그냥 호기심, 여기에서 가져온 하나의 좋은 방법이야 http://code.activestate.com/recipes/252178/는 :

def all_perms(elements):
    if len(elements) <=1:
        yield elements
    else:
        for perm in all_perms(elements[1:]):
            for i in range(len(elements)):
                # nb elements[0:1] works in both string and list contexts
                yield 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 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

그리고 또 다른 기반으로 itertools.product:

def permutations(iterable, r=None):
    pool = tuple(iterable)
    n = len(pool)
    r = n if r is None else r
    for indices in product(range(n), repeat=r):
        if len(set(indices)) == r:
            yield tuple(pool[i] for i in indices)

14
이 목록과 다른 재귀 솔루션은 순열 된 목록이 충분히 크면 모든 RAM을 차지할 수있는 잠재적 위험이 있습니다.
— Boris Gorelik

3
그들은 또한 큰 목록으로 재귀 한계에 도달하고 죽습니다
— dbr

58
bgbg, dbr : 생성기를 사용하므로 함수 자체는 메모리를 소모하지 않습니다. all_perms에 의해 리턴 된 반복자를 소비하는 방법에 대해 설명합니다 (각 반복을 디스크에 쓸 수 있고 메모리에 대해 걱정하지 않아도됩니다). 이 게시물이 오래되었다는 것을 알고 있지만 지금 읽고있는 모든 사람의 이익을 위해이 글을 쓰고 있습니다. 또한 이제 가장 좋은 방법은 많은 사람들이 지적한 것처럼 itertools.permutations ()를 사용하는 것입니다.
— Jagtesh Chadha

18
다만 발전기. 명확하지 않은 경우 중첩 생성기를 사용하여 호출 스택 위로 이전 생성기를 생성합니다. O (n) 메모리를 사용하므로 좋습니다.
— cdunn2001

1
추신 : 나는 for i in range(len(elements))대신에 그것을 고쳤다 for i in range(len(elements)+1). 실제로, 단일 요소 elements[0:1]는 len(elements)다른 위치에 있을 수 있으며 결과적으로는 아닙니다 len(elements)+1.
— Eric O Lebigot

339

그리고 파이썬 2.6 부터 :

import itertools
itertools.permutations([1,2,3])

(생성기 list(permutations(l))로 반환. 목록으로 반환하는 데 사용합니다.)


15
Python 3에서도 작동
— wheleph

10
r예를 들어 itertools.permutations([1,2,3], r=2), 2 개의 요소를 선택하여 가능한 모든 순열을 생성 하는 매개 변수 가 있습니다 .[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
— toto_tico

277

Python 2.6 이상의 다음 코드 만

먼저 수입 itertools:

import itertools

순열 (순서가 중요 함) :

print list(itertools.permutations([1,2,3,4], 2))
[(1, 2), (1, 3), (1, 4),
(2, 1), (2, 3), (2, 4),
(3, 1), (3, 2), (3, 4),
(4, 1), (4, 2), (4, 3)]

조합 (순서는 중요하지 않음) :

print list(itertools.combinations('123', 2))
[('1', '2'), ('1', '3'), ('2', '3')]

카티 전 곱 (여러 개의 반복 가능) :

print list(itertools.product([1,2,3], [4,5,6]))
[(1, 4), (1, 5), (1, 6),
(2, 4), (2, 5), (2, 6),
(3, 4), (3, 5), (3, 6)]

데카르트 곱 (반복 가능 및 자체) :

print list(itertools.product([1,2], repeat=3))
[(1, 1, 1), (1, 1, 2), (1, 2, 1), (1, 2, 2),
(2, 1, 1), (2, 1, 2), (2, 2, 1), (2, 2, 2)]


`print list (itertools.permutations ([1,2,3,4], 2)) ^`SyntaxError : invalid syntax` VS 코드를 사용하여 시작했습니다. 내가 뭘 잘못 했나요? 포인터가 "list"의 "t"아래를 가리키고 있습니다.
— gus

39
def permutations(head, tail=''):
    if len(head) == 0: print tail
    else:
        for i in range(len(head)):
            permutations(head[0:i] + head[i+1:], tail+head[i])

호출

permutations('abc')

왜 꼬리를 인쇄 한 다음 없음을 반환합니까? 왜 꼬리를 돌려주지 않겠습니까? 어쨌든 아무것도 돌려주지 않겠습니까?
— bugmenot123

30
#!/usr/bin/env python

def perm(a, k=0):
   if k == len(a):
      print a
   else:
      for i in xrange(k, len(a)):
         a[k], a[i] = a[i] ,a[k]
         perm(a, k+1)
         a[k], a[i] = a[i], a[k]

perm([1,2,3])

산출:

[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 2, 1]
[3, 1, 2]

목록의 내용을 바꿀 때 입력으로 가변 시퀀스 유형이 필요합니다. 예 perm(list("ball"))를 들어 작동합니다perm("ball") 문자열을 변경할 수 없기 때문에 하지 않습니다.

이 Python 구현은 Horowitz, Sahni 및 Rajasekeran의 Computer Algorithms 책에 제시된 알고리즘에서 영감을 얻었습니다 .


k는 길이 또는 순열이라고 가정합니다. k = 2의 경우 출력 [1, 2, 3]. (1, 2) (1, 3) (2, 1) (2, 3) (3, 1) (3, 2) 여야합니까?
— Konstantinos Monachopoulos

k는 교환하려는 요소의 색인입니다.
— sf8193

22

이 솔루션은 메모리에서 모든 순열을 유지하지 않도록 생성기를 구현합니다.

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

16

기능적인 스타일

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)])

결과:

[[0, 1, 2], [1, 0, 2], [1, 2, 0], [0, 2, 1], [2, 0, 1], [2, 1, 0]]

15

다음 코드는 생성자로 구현 된 주어진 목록의 전체 순열입니다. 목록에 대한 참조 만 반환하므로 생성기 외부에서 목록을 수정해서는 안됩니다. 이 솔루션은 비 재귀 적이므로 메모리가 부족합니다. 입력 목록에있는 여러 개의 요소 사본에도 적합합니다.

def permute_in_place(a):
    a.sort()
    yield list(a)

    if len(a) <= 1:
        return

    first = 0
    last = len(a)
    while 1:
        i = last - 1

        while 1:
            i = i - 1
            if a[i] < a[i+1]:
                j = last - 1
                while not (a[i] < a[j]):
                    j = j - 1
                a[i], a[j] = a[j], a[i] # swap the values
                r = a[i+1:last]
                r.reverse()
                a[i+1:last] = r
                yield list(a)
                break
            if i == first:
                a.reverse()
                return

if __name__ == '__main__':
    for n in range(5):
        for a in permute_in_place(range(1, n+1)):
            print a
        print

    for a in permute_in_place([0, 0, 1, 1, 1]):
        print a
    print

15

내 의견으로는 매우 분명한 방법은 다음과 같습니다.

def permutList(l):
    if not l:
            return [[]]
    res = []
    for e in l:
            temp = l[:]
            temp.remove(e)
            res.extend([[e] + r for r in permutList(temp)])

    return res

11
list2Perm = [1, 2.0, 'three']
listPerm = [[a, b, c]
            for a in list2Perm
            for b in list2Perm
            for c in list2Perm
            if ( a != b and b != c and a != c )
            ]
print listPerm

산출:

[
    [1, 2.0, 'three'], 
    [1, 'three', 2.0], 
    [2.0, 1, 'three'], 
    [2.0, 'three', 1], 
    ['three', 1, 2.0], 
    ['three', 2.0, 1]
]

2
기술적으로 원하는 출력을 생성하는 동안 O (n ^ n)에서 O (n lg n) 일 수있는 무언가를 해결하고 있습니다. 큰 세트의 경우 "약간"비효율적입니다.
— James

3
@ 제임스 : 나는 당신이주는 O (n log n)에 약간 혼란 스럽습니다 : 순열의 수는 n!이며, 이미 O (n log n)보다 훨씬 큽니다. 그래서 솔루션이 어떻게 O (n log n) 일 수 있는지 알 수 없습니다. 그러나이 솔루션은 스털링의 근사치에서 알 수 있듯이 O (n ^ n)에 있으며 n보다 훨씬 큽니다.
— Eric O Lebigot

9

계승 수 체계 에 기반한 알고리즘을 사용했습니다. 길이 n의 목록에 대해 각 단계에서 남은 항목 중에서 선택하여 각 순열 항목을 항목별로 어셈블 할 수 있습니다. 첫 번째 항목에는 n 개, 두 번째 항목에는 n-1, 마지막 항목에는 하나만 선택할 수 있으므로 계승 수 시스템의 숫자를 숫자로 사용할 수 있습니다. 이런 식으로 0에서 n! -1까지의 숫자는 사전 순으로 가능한 모든 순열에 해당합니다.

from math import factorial
def 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/placeValue
            newPermutation.append(available.pop(index))
            x-=index*placeValue
        permutations.append(newPermutation)
    return permutations

permutations(range(3))

산출:

[[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]

이 방법은 비재 귀적이지만 내 컴퓨터에서는 약간 느리고 xrange는 n 일 때 오류를 발생시킵니다! C long 정수로 변환하기에는 너무 큽니다 (n = 13). 내가 필요할 때 충분했지만 긴 샷으로는 itertools.permutations가 아닙니다.


3
안녕하세요, Stack Overflow에 오신 것을 환영합니다. 무차별 대입 방법을 게시하면 장점이 있지만 솔루션이 허용되는 솔루션보다 낫다고 생각하지 않는 경우에는 솔루션을 게시하지 않아야합니다 (특히 이미 많은 답변이있는 오래된 질문에 대해).
— Hannele

1
나는 실제로 무차별 라이브러리 접근 방식을 찾고 있었으므로 감사합니다!
— Jay Taylor

8

이 알고리즘은 n factorial시간이 복잡 n하므로 입력 목록의 길이는 어디 입니까?

실행 결과를 인쇄하십시오.

global result
result = [] 

def permutation(li):
if li == [] or li == None:
    return

if len(li) == 1:
    result.append(li[0])
    print result
    result.pop()
    return

for i in range(0,len(li)):
    result.append(li[i])
    permutation(li[:i] + li[i+1:])
    result.pop()    

예:

permutation([1,2,3])

산출:

[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]

8

tzwenn의 답변에서와 같이 실제로 각 순열의 첫 번째 요소를 반복 할 수 있습니다. 그러나이 방법으로이 솔루션을 작성하는 것이 더 효율적입니다.

def all_perms(elements):
    if len(elements) <= 1:
        yield elements  # Only permutation possible = no permutation
    else:
        # 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

이 솔루션은 약 30 % 더 빠릅니다 . len(elements) <= 1대신으로 끝나는 재귀 덕분 입니다 0. yieldRiccardo Reyes의 솔루션과 같이 생성기 함수 (를 통해 )를 사용하기 때문에 메모리 효율성이 훨씬 뛰어납니다.


6

이것은 목록 이해를 사용하는 Haskell 구현에서 영감을 얻었습니다.

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

6

정규 구현 (수율 없음-메모리의 모든 것을 수행함) :

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 item
        perms = 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 array
    else:
        for i in range(len(array)):
            perms = getPermutations(array[:i] + array[i+1:])
            for p in perms:
                yield [array[i], *p]

기본적인 아이디어는 제 1 위치에 배열의 모든 요소를 통해 이동 한 다음 2 위치에 제 1의 선택 요소없이 모든 요소 나머지 가서하는 등 당신은이 작업을 수행 할 수 재귀 의 중지 기준은 1 요소의 배열에 도달합니다.이 경우 해당 배열을 반환합니다.

여기에 이미지 설명을 입력하십시오


이것은 나를 위해 작동하지 않습니다 _> ValueError : 피연산자는 이 줄에 대해 모양 (0,) (2,)과 함께 브로드 캐스트 할 수 없습니다 .perms = getPermutations(array[:i] + array[i+1:])
— RK1

@ RK1 입력은 무엇입니까?
— David Refaeli

나는 numpy배열 _>을 전달하고 있는데 getPermutations(np.array([1, 2, 3])), 목록에 대해 작동하는 것을 보았습니다. func arg가 다음과 같이 혼란스러워졌습니다 array:)
— RK1

@ RK1 : 그것이 작동한다는 것은 기쁘다 :-) list는 파이썬의 키워드이므로 일반적으로 매개 변수를 키워드로 호출하는 것은 좋지 않습니다. 그래서 배열이라는 단어 배열을 사용합니다. 이것은 내가 사용하는 목록의 실제 기능이므로 배열과 같은 방식입니다. 나는 문서를 작성한다면 그것을 명확히 할 것이라고 생각합니다. 또한 기본적인 "인터뷰"질문은 numpy와 같은 외부 패키지없이 해결되어야한다고 생각합니다.
— David Refaeli

하하, 맞아요. 예, 사용하려고 numba했고 속도에 욕심이 numpy
— 생겨서

4

성능을 위해 Knuth 에서 영감을 얻은 numpy 솔루션 (p22) :

from numpy import empty, uint8
from math import factorial

def perms(n):
    f = 1
    p = empty((2*n-1, factorial(n)), uint8)
    for i in range(n):
        p[i, :f] = i
        p[i+1:2*i+1, :f] = p[:i, :f]  # constitution de blocs
        for j in range(i):
            p[:i+1, f*(j+1):f*(j+2)] = p[j+1:j+i+2, :f]  # copie de blocs
        f = f*(i+1)
    return p[:n, :]

많은 양의 메모리를 복사하면 시간이 절약됩니다 list(itertools.permutations(range(n)).

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

3
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 - 1
        found = 0
        while (not found and i>0):
            if p[i]<p[i+1]:
                found = 1
            else:
                i = i - 1
        k = n
        while p[i]>p[k]:
            k = k - 1
        aux = p[i]
        p[i] = p[k]
        p[k] = aux
        for j in range(1,(n-i)/2+1):
            aux = p[i+j]
            p[i+j] = p[n-j+1]
            p[n-j+1] = aux
        if not found:
            break

perm(5)

3

다음은 https://stackoverflow.com/a/108651/184528 의 Ber 솔루션과 유사한 새 중간 목록을 만들지 않고 목록에서 작동하는 알고리즘입니다 .

def permute(xs, low=0):
    if low + 1 >= len(xs):
        yield xs
    else:
        for p in permute(xs, low + 1):
            yield p        
        for i in range(low + 1, len(xs)):        
            xs[low], xs[i] = xs[i], xs[low]
            for p in permute(xs, low + 1):
                yield p        
            xs[low], xs[i] = xs[i], xs[low]

for p in permute([1, 2, 3, 4]):
    print p

당신은 여기에 자신을 위해 코드를 시도 할 수 있습니다 : http://repl.it/J9v


3

재귀의 아름다움 :

>>> import copy
>>> def perm(prefix,rest):
...      for e in rest:
...              new_rest=copy.copy(rest)
...              new_prefix=copy.copy(prefix)
...              new_prefix.append(e)
...              new_rest.remove(e)
...              if len(new_rest) == 0:
...                      print new_prefix + new_rest
...                      continue
...              perm(new_prefix,new_rest)
... 
>>> perm([],['a','b','c','d'])
['a', 'b', 'c', 'd']
['a', 'b', 'd', 'c']
['a', 'c', 'b', 'd']
['a', 'c', 'd', 'b']
['a', 'd', 'b', 'c']
['a', 'd', 'c', 'b']
['b', 'a', 'c', 'd']
['b', 'a', 'd', 'c']
['b', 'c', 'a', 'd']
['b', 'c', 'd', 'a']
['b', 'd', 'a', 'c']
['b', 'd', 'c', 'a']
['c', 'a', 'b', 'd']
['c', 'a', 'd', 'b']
['c', 'b', 'a', 'd']
['c', 'b', 'd', 'a']
['c', 'd', 'a', 'b']
['c', 'd', 'b', 'a']
['d', 'a', 'b', 'c']
['d', 'a', 'c', 'b']
['d', 'b', 'a', 'c']
['d', 'b', 'c', 'a']
['d', 'c', 'a', 'b']
['d', 'c', 'b', 'a']

3

이 알고리즘은 가장 효과적인 알고리즘으로, 반복 호출에서 배열 전달 및 조작을 피하고 Python 2, 3에서 작동합니다.

def permute(items):
    length = len(items)
    def inner(ix=[]):
        do_yield = len(ix) == length - 1
        for i in range(0, length):
            if i in ix: #avoid duplicates
                continue
            if do_yield:
                yield tuple([items[y] for y in ix + [i]])
            else:
                for p in inner(ix + [i]):
                    yield p
    return 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)

3
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 seq
    else:
        return pzip(seq[0], perm(seq[1:]))

3

다른 접근법 (libs없이)

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

입력은 문자열 또는 목록 일 수 있습니다

print(permutation('abcd'))
print(permutation(['a', 'b', 'c', 'd']))

예를 들어 정수가있는 목록에는 작동하지 않습니다. [1, 2, 3]반환[6, 6, 6, 6, 6, 6]
— RK1

@ RK1, 당신은 이것을 시도 할 수 있습니다print(permutation(['1','2','3']))
— Tatsu

감사합니다
— RK1

3

면책 조항 : 패키지 작성자의 모양이없는 플러그. :)

트로터의 실제로 순열을 포함하지만, 같이 오히려, 순열의 매우 큰 '목록'과 함께 작업에 가능하게 오더링에 순열과 각각의 위치 사이의 매핑을 설명하지 않는 의사 목록을 생성한다는 점에서 패키지는 대부분의 구현과 다른 에서 이 데모 하는 수행 일반적인 웹 페이지보다 더 많은 메모리를 사용하거나 처리하지 않고, 알파벳 문자의 모든 순열을 '포함'의사 목록에서 운영 및 룩업 꽤 순간.

어쨌든 순열 목록을 생성하려면 다음을 수행하십시오.

import trotter

my_permutations = trotter.Permutations(3, [1, 2, 3])

print(my_permutations)

for p in my_permutations:
    print(p)

산출:

[1, 2, 3]의 6 개의 3 개의 순열을 포함하는 의사 목록.
[1, 2, 3]
[1, 3, 2]
[3, 1, 2]
[3, 2, 1]
[2, 3, 1]
[2, 1, 3]

2

가능한 모든 순열 생성

python3.4를 사용하고 있습니다.

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 = temp
    return result

테스트 사례 :

lst = [1, 2, 3, 4]
#lst = ["yellow", "magenta", "white", "blue"]
seq = 2
final = calcperm(lst, seq)
print(len(final))
print(final)

2

검색 및 실험 시간을 절약하기 위해 Numba와 함께 작동하는 Python의 비 재귀 순열 솔루션은 다음과 같습니다 (0.41 현재).

@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 r
permutations([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

따라서 njitted 함수에서 호출해야하는 경우에만이 버전을 사용하십시오. 그렇지 않으면 itertools 구현을 선호하십시오.


1

나는 볼 을 많이 반복이 재귀 함수, 정확히 안쪽에가는 순수 재귀 ...

단일 루프조차도 준수 할 수없는 분들을 위해, 여기에는 완전히 불필요한 완전히 재귀적인 솔루션이 있습니다.

def all_insert(x, e, i=0):
    return [x[0:i]+[e]+x[i:]] + all_insert(x,e,i+1) if i<len(x)+1 else []

def for_each(X, e):
    return all_insert(X[0], e) + for_each(X[1:],e) if X else []

def permute(x):
    return [x] if len(x) < 2 else for_each( permute(x[1:]) , x[0])


perms = permute([1,2,3])

1

다른 해결책 :

def permutation(flag, k =1 ):
    N = len(flag)
    for i in xrange(0, N):
        if flag[i] != 0:
            continue
        flag[i] = k 
        if k == N:
            print flag
        permutation(flag, k+1)
        flag[i] = 0

permutation([0, 0, 0])

0

내 파이썬 솔루션 :

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") )

0
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']


0

사용 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]]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.