Angenommen, ich habe eine Liste von n Elementen, ich weiß, dass es n gibt! Möglichkeiten, diese Elemente zu bestellen. Was ist ein Algorithmus, um alle möglichen Ordnungen dieser Liste zu generieren? Beispiel, ich habe Liste [a, b, c]. Der Algorithmus würde [[a, b, c], [a, c, b], [b, a, c], [b, c, a], [c, a, b], [c, b] zurückgeben , ein]].
Ich lese dies hier http://en.wikipedia.org/wiki/Permutation#Algorithms_to_generate_permutations
Aber Wikipedia hat es nie gut erklärt. Ich verstehe nicht viel davon.
algorithm
list
permutation
fent
quelle
quelle
Antworten:
Grundsätzlich werden für jedes Element von links nach rechts alle Permutationen der verbleibenden Elemente generiert (und jedes wird mit den aktuellen Elementen hinzugefügt). Dies kann rekursiv (oder iterativ, wenn Sie Schmerzen mögen) erfolgen, bis der letzte Punkt erreicht ist und an diesem Punkt nur noch eine mögliche Reihenfolge vorliegt.
Mit der Liste [1,2,3,4] werden also alle Permutationen generiert, die mit 1 beginnen, dann alle Permutationen, die mit 2 beginnen, dann 3 und dann 4.
Dies reduziert effektiv das Problem vom Finden von Permutationen einer Liste von vier Elementen auf eine Liste von drei Elementen. Nach dem Reduzieren auf 2 und dann 1 Artikellisten werden alle gefunden.
Beispiel für Prozesspermutationen mit 3 farbigen Kugeln:
(von https://en.wikipedia.org/wiki/Permutation#/media/File:Permutations_RGB.svg - https://commons.wikimedia.org/wiki/File:Permutations_RGB. svg )
quelle
Hier ist ein Algorithmus in Python, der auf einem Array funktioniert:
Sie können den Code hier selbst ausprobieren: http://repl.it/J9v
quelle
Hier gibt es bereits viele gute Lösungen, aber ich möchte mitteilen, wie ich dieses Problem selbst gelöst habe, und hoffe, dass dies für jemanden hilfreich sein kann, der auch seine eigene Lösung ableiten möchte.
Nach einigem Nachdenken über das Problem habe ich zwei folgende Schlussfolgerungen gezogen:
L
der Größenn
gibt es die gleiche Anzahl von Lösungen, beginnend mit L 1 , L 2 ... L n Elementen der Liste. Da es insgesamtn!
Permutationen der Größenliste gibtn
, erhalten wirn! / n = (n-1)!
Permutationen in jeder Gruppe.[a,b]
und[b,a]
.Mit diesen beiden einfachen Ideen habe ich den folgenden Algorithmus abgeleitet:
So habe ich das in C # implementiert:
quelle
Die Antwort von Wikipedia auf "lexikografische Reihenfolge" erscheint mir im Kochbuchstil vollkommen explizit. Es zitiert einen Ursprung des Algorithmus aus dem 14. Jahrhundert!
Ich habe gerade eine schnelle Implementierung des Wikipedia-Algorithmus in Java geschrieben, um dies zu überprüfen, und es war kein Problem. Aber was Sie in Ihrem Q als Beispiel haben, ist NICHT "alle Permutationen auflisten", sondern "eine LISTE aller Permutationen", so dass Wikipedia für Sie keine große Hilfe sein wird. Sie benötigen eine Sprache, in der Listen von Permutationen erstellt werden können. Und glauben Sie mir, einige Milliarden lange Listen werden normalerweise nicht in imperativen Sprachen behandelt. Sie möchten wirklich eine nicht strenge funktionale Programmiersprache, in der Listen ein erstklassiges Objekt sind, um Dinge herauszuholen, ohne die Maschine dem Hitzetod des Universums nahe zu bringen.
Das ist einfach. In Standard-Haskell oder einer modernen FP-Sprache:
und
quelle
Wie WhirlWind sagte, fängst du am Anfang an.
Sie tauschen den Cursor mit jedem verbleibenden Wert aus, einschließlich des Cursors selbst. Dies sind alles neue Instanzen (ich habe ein
int[]
undarray.clone()
im Beispiel verwendet).Führen Sie dann Permutationen für alle diese verschiedenen Listen durch und stellen Sie sicher, dass sich der Cursor rechts befindet.
Wenn keine verbleibenden Werte mehr vorhanden sind (der Cursor befindet sich am Ende), drucken Sie die Liste. Dies ist die Stoppbedingung.
quelle
Rekursiv erfordert immer einige mentale Anstrengungen, um aufrechtzuerhalten. Und für große Zahlen ist die Fakultät leicht riesig und der Stapelüberlauf wird leicht ein Problem sein.
Für kleine Zahlen (3 oder 4, was meistens vorkommt) sind mehrere Schleifen recht einfach und unkompliziert. Es ist bedauerlich, dass Antworten mit Schleifen nicht bewertet wurden.
Beginnen wir mit der Aufzählung (und nicht mit der Permutation). Lesen Sie den Code einfach als Pseudo-Perl-Code.
Aufzählung tritt häufiger auf als Permutation. Wenn jedoch eine Permutation erforderlich ist, fügen Sie einfach die folgenden Bedingungen hinzu:
Wenn Sie nun wirklich eine allgemeine Methode für große Listen benötigen, können wir die Radix-Methode verwenden. Betrachten Sie zunächst das Aufzählungsproblem:
Das Radix-Inkrement ist im Wesentlichen die Zählung von Zahlen (in der Basis der Anzahl der Listenelemente).
Wenn Sie nun Permutaion benötigen, fügen Sie einfach die Checks in die Schleife ein:
Bearbeiten: Der obige Code sollte funktionieren, aber für die Permutation könnte radix_increment verschwenderisch sein. Wenn also Zeit ein praktisches Anliegen ist, müssen wir radix_increment in permute_inc ändern:
Natürlich ist dieser Code jetzt logisch komplexer, ich werde ihn dem Leser überlassen.
quelle
Referenz: Geeksforgeeks.org
quelle
Wenn sich jemand fragt, wie man in Permutation in Javascript vorgeht.
Idee / Pseudocode
beispielsweise. 'a' + permutieren (bc). Permute von bc wäre bc & cb. Fügen Sie nun diese beiden hinzu, um abc, acb zu erhalten. In ähnlicher Weise wird durch Auswahl von b + permute (ac) bac, bca ... provoziert und weitergemacht.
Schauen Sie sich jetzt den Code an
Nehmen Sie sich Zeit, um dies zu verstehen. Ich habe diesen Code erhalten von ( Pertumation in JavaScript )
quelle
Ein anderes in Python, es ist nicht als @ cdiggins vorhanden, aber ich denke, es ist einfacher zu verstehen
quelle
Ich dachte daran, einen Code zu schreiben, um die Permutationen einer bestimmten Ganzzahl beliebiger Größe zu erhalten, dh mit einer Zahl von 4567 erhalten wir alle möglichen Permutationen bis 7654 ... Also arbeitete ich daran und fand einen Algorithmus und implementierte ihn schließlich hier ist der in "c" geschriebene Code. Sie können es einfach kopieren und auf beliebigen Open Source-Compilern ausführen. Einige Fehler warten jedoch darauf, behoben zu werden. Bitte schätzen.
Code:
quelle
Ich habe diesen erstellt. basierend auf zu permutierten Forschungsergebnissen (qwe, 0, qwe.length-1); Nur damit Sie wissen, können Sie es mit oder ohne Backtrack tun
quelle
Hier ist eine Spielzeug-Ruby-Methode, die so funktioniert und
#permutation.to_a
für verrückte Leute möglicherweise besser lesbar ist. Es ist hella langsam, aber auch 5 Zeilen.quelle
Ich habe diese rekursive Lösung in ANSI C geschrieben. Jede Ausführung der Permutate-Funktion bietet eine andere Permutation, bis alle abgeschlossen sind. Globale Variablen können auch für die Variablen Fakt und Anzahl verwendet werden.
quelle
Java-Version
Z.B
Ausgabe:
quelle
in PHP
quelle
Hier ist der Code in Python zum Drucken aller möglichen Permutationen einer Liste:
Ich habe einen lexikografischen Ordnungsalgorithmus verwendet, um alle möglichen Permutationen zu erhalten, aber ein rekursiver Algorithmus ist effizienter. Den Code für den rekursiven Algorithmus finden Sie hier: Python-Rekursionspermutationen
quelle
quelle
In der Scala
quelle
Dies ist eine Java-Version für die Permutation
quelle
Hier ist eine Implementierung für ColdFusion (erfordert CF10 aufgrund des Merge-Arguments zu ArrayAppend ()):
Basierend auf der obigen js-Lösung von KhanSharp.
quelle
Ich weiß, dass dies im heutigen Stackoverflow ein sehr sehr altes und sogar nicht zum Thema gehörendes Thema ist, aber ich wollte trotzdem eine freundliche Javascript-Antwort beisteuern, aus dem einfachen Grund, dass es in Ihrem Browser ausgeführt wird.
Ich habe auch den
debugger
Direktiven-Haltepunkt hinzugefügt, damit Sie den Code (Chrome erforderlich) schrittweise durchgehen können, um zu sehen, wie dieser Algorithmus funktioniert. Öffnen Sie Ihre Entwicklungskonsole in Chrome (F12
in Windows oderCMD + OPTION + I
Mac) und klicken Sie dann auf "Code-Snippet ausführen". Dies implementiert denselben exakten Algorithmus, den @WhirlWind in seiner Antwort vorgestellt hat.Ihr Browser sollte die Ausführung an der
debugger
Direktive anhalten. VerwendenF8
diese , um die Codeausführung fortzusetzen.Gehen Sie den Code durch und sehen Sie, wie es funktioniert!
quelle
In der folgenden Java-Lösung nutzen wir die Tatsache, dass Strings unveränderlich sind, um zu vermeiden, dass die Ergebnismenge bei jeder Iteration geklont wird.
Die Eingabe ist ein String, sagen wir "abc", und die Ausgabe enthält alle möglichen Permutationen:
Code:
Der gleiche Ansatz kann auf Arrays angewendet werden (anstelle einer Zeichenfolge):
quelle
Es ist meine Lösung für Java:
quelle
Sie können nicht wirklich über die Lösung eines Permultationsproblems in Rekursion sprechen, ohne eine Implementierung in einer (Dialekt-) Sprache zu veröffentlichen, die Pionierarbeit für die Idee geleistet hat . Der Vollständigkeit halber ist hier eine der Möglichkeiten, die in Schema ausgeführt werden können.
Anruf bekommen
(permof (list "foo" "bar" "baz"))
wir:Ich werde nicht auf die Details des Algorithmus eingehen, da dies in anderen Beiträgen ausreichend erklärt wurde. Die Idee ist die gleiche.
Rekursive Probleme sind jedoch in destruktiven Medien wie Python, C und Java viel schwieriger zu modellieren und zu berücksichtigen, während sie in Lisp oder ML präzise ausgedrückt werden können.
quelle
Hier ist eine rekursive Lösung in PHP. WhirlWinds Beitrag beschreibt die Logik genau. Es ist erwähnenswert, dass das Generieren aller Permutationen in faktorieller Zeit erfolgt. Daher ist es möglicherweise eine gute Idee, stattdessen einen iterativen Ansatz zu verwenden.
Die strDiff-Funktion verwendet zwei Zeichenfolgen
s1
unds2
und gibt eine neue Zeichenfolge zurück, in der alless1
ohne Elemente enthalten ists2
(Duplikate sind wichtig). Also,strDiff('finish','i')
=>'fnish'
(das zweite 'i' wird nicht entfernt).quelle
Hier ist ein Algorithmus in R für den Fall, dass jemand vermeiden muss, zusätzliche Bibliotheken zu laden, wie ich es musste.
Anwendungsbeispiel:
quelle
quelle
Dies ist ein rekursiver Code für Java. Die Idee ist, ein Präfix zu haben, das den Rest der Zeichen hinzufügt:
Beispiel:
Eingabe = "ABC"; Ausgabe:
ABC ACB BAC BCA CAB CBA
quelle
str
wenn Sie rekursiv anrufen, sonst wird es nicht beendet.Nur um vollständig zu sein, C ++
...
quelle
Hier ist eine nicht rekursive Lösung in C ++, die die nächste Permutation in aufsteigender Reihenfolge bereitstellt, ähnlich der Funktionalität von std :: next_permutation:
quelle