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


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.