844 Stimmen

Wie kann man alle Permutationen einer Liste erzeugen?

Wie erzeugt man in Python alle Permutationen einer Liste, unabhängig vom Typ der Elemente in dieser Liste?

Zum Beispiel:

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]

9 Stimmen

Ich stimme mit der rekursiven, akzeptierten Antwort überein - HEUTE. Das Problem ist jedoch immer noch ein großes Problem der Informatik. Die akzeptierte Antwort löst dieses Problem mit exponentieller Komplexität (2^N N=len(list)) Lösen Sie es (oder beweisen Sie, dass Sie es nicht können) in Polynomialzeit :) Siehe "Travelling-Salesman-Problem".

60 Stimmen

@FlipMcF Es wird schwierig sein, es in Polynomialzeit zu "lösen", da es faktorielle Zeit braucht, um auch nur die Ausgabe aufzuzählen... also, nein, es ist nicht möglich.

0 Stimmen

@FlipMcF: Nein, das ist es nicht wirklich: a) nur um die optimal Lösung, nicht gut genug Lösungen, die für reale Zwecke gut genug sind, und b) wir müssen nicht alle Knoten im Suchraum, d. h. alle Permutationen, erweitern; das ist es, was heuristische Algorithmen wie A*

24voto

Ricardo Reyes Punkte 12408

Bei dieser Lösung wird ein Generator implementiert, um zu vermeiden, dass alle Permutationen im Speicher gehalten werden:

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

20voto

Paolo Punkte 199

In einem funktionalen Stil

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

Das Ergebnis:

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

20voto

Maverick Meerkat Punkte 4734

Reguläre Implementierung (keine Ausbeute - wird alles im Speicher erledigt):

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

Umsetzung der Rendite:

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]

Die Grundidee ist, alle Elemente im Array für die 1. Position durchzugehen, und dann in der 2. Position alle restlichen Elemente ohne das ausgewählte Element für die 1. Sie können dies tun mit Rekursion , wobei das Stoppkriterium darin besteht, ein Array mit 1 Element zu erreichen - in diesem Fall geben Sie dieses Array zurück.

enter image description here

17voto

tzwenn Punkte 303

Ein ganz offensichtlicher Weg könnte meiner Meinung nach auch sein:

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

17voto

Ber Punkte 37347

Der folgende Code ist eine in-place-Permutation einer gegebenen Liste, implementiert als Generator. Da er nur Verweise auf die Liste zurückgibt, sollte die Liste außerhalb des Generators nicht verändert werden. Die Lösung ist nicht rekursiv und verbraucht daher wenig Speicher. Sie funktioniert auch gut mit mehreren Kopien von Elementen in der Eingabeliste.

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X