Eine häufige Aufgabe beim Programmieren von Interviews (allerdings nicht aus meiner Erfahrung mit Interviews) besteht darin, eine Zeichenfolge oder eine Ganzzahl zu nehmen und jede mögliche Permutation aufzulisten.
Gibt es ein Beispiel dafür und die Logik zur Lösung eines solchen Problems?
Ich habe ein paar Code-Schnipsel gesehen, aber sie waren nicht gut kommentiert / erklärt und daher schwer zu folgen.
c#
algorithm
permutation
GurdeepS
quelle
quelle
Antworten:
Zuallererst: Es riecht natürlich nach Rekursion !
Da Sie auch das Prinzip kennenlernen wollten, habe ich mein Bestes getan, um es in der menschlichen Sprache zu erklären. Ich denke, Rekursion ist meistens sehr einfach. Sie müssen nur zwei Schritte erfassen:
In der menschlichen Sprache :
Ich habe den Pseudocode unter http://www.programmersheaven.com/mb/Algorithms/369713/369713/permutation-algorithm-help/ gefunden :
C #
OK, und etwas ausführlicheres (und da es mit c # gekennzeichnet ist) von http://radio.weblogs.com/0111551/stories/2002/10/14/permutations.html : Ziemlich lang, aber ich habe beschlossen, es zu kopieren sowieso ist der Beitrag also nicht vom Original abhängig.
ABC, ACB, BAC, BCA, CAB, CBA.
Code:
quelle
Swap(ref list[k], ref list[i]);
) ist nicht erforderlich.(a[x], a[y]) = (a[y], a[x]);
Es sind nur zwei Codezeilen, wenn LINQ verwendet werden darf. Bitte sehen Sie meine Antwort hier .
BEARBEITEN
Hier ist meine generische Funktion, die alle Permutationen (keine Kombinationen) aus einer Liste von T zurückgeben kann:
Beispiel:
Ausgabe - eine Liste von Ganzzahllisten:
Da diese Funktion LINQ verwendet, ist .net 3.5 oder höher erforderlich.
quelle
const string s = "HALLOWEEN";
var result = GetPermutations(Enumerable.Range(0, s.Length), s.Length).Select(t => t.Select(i => s[i]));
Hier habe ich die Lösung gefunden. Es wurde in Java geschrieben, aber ich habe es in C # konvertiert. Ich hoffe es hilft dir.
Hier ist der Code in C #:
quelle
Eine Rekursion ist nicht erforderlich. Hier finden Sie gute Informationen zu dieser Lösung.
Ich habe diesen Algorithmus seit Jahren verwendet, hat es O (N) Zeit und Raum Komplexität berechnen jeweils Permutation .
quelle
O(N-1)
für die Sequenz undO(N)
für die SwapsO(N)
. Und ich benutze dies immer noch in der Produktion, aber mit einem Refactor, um nur eine Permutation zu generieren, wie:GetPermutation(i)
wo0 <= i <= N!-1
. Gerne verwende ich etwas mit einer besseren Leistung als dieses. Rufen Sie also eine Referenz für etwas Besseres an, die meisten Alternativen werdenO(N!)
im Speicher verwendet, damit Sie dies auch überprüfen können.Sie können Ihre Swap-Funktion schreiben, um Zeichen auszutauschen.
Dies ist als permute (string, 0) zu bezeichnen;
quelle
Zuallererst haben Mengen Permutationen, keine Zeichenketten oder Ganzzahlen, also gehe ich einfach davon aus, dass Sie "die Zeichensätze in einer Zeichenkette" meinen.
Beachten Sie, dass ein Satz der Größe n n hat! n-Permutationen.
Der folgende Pseudocode (aus Wikipedia), aufgerufen mit k = 1 ... n! wird alle Permutationen geben:
Hier ist der entsprechende Python-Code (für 0-basierte Array-Indizes):
quelle
k := k / j;
.Leicht modifizierte Version in C #, die die erforderlichen Permutationen in einem Array vom Typ ANY liefert.
quelle
Permutations(vals).ToArray()
Sie N Verweise auf dasselbe Array. Wenn Sie die Ergebnisse speichern möchten, müssen Sie manuell eine Kopie erstellen. ZBPermutations(values).Select(v => (T[])v.Clone())
quelle
Ich mochte den FBryant87- Ansatz, da er einfach ist. Leider bietet es wie viele andere "Lösungen" nicht alle Permutationen oder zB eine ganze Zahl, wenn es dieselbe Ziffer mehr als einmal enthält. Nehmen Sie als Beispiel 656123. Die Linie:
mit Ausnahme werden alle Vorkommen verursachen entfernt werden, das heißt , wenn c = 6 sind zwei Stellen entfernt , und wir sind links mit zB 5123 Da keine der Lösungen , die ich dieses Problem gelöst versucht, entschied ich mich , um zu versuchen und es zu lösen mich von FBryant87 ‚s Code als Basis. Folgendes habe ich mir ausgedacht:
Ich entferne einfach das erste gefundene Vorkommen mit .Remove und .IndexOf. Scheint zumindest für meinen Gebrauch wie vorgesehen zu funktionieren. Ich bin sicher, es könnte klüger gemacht werden.
Beachten Sie jedoch Folgendes: Die resultierende Liste kann Duplikate enthalten. Stellen Sie daher sicher, dass Sie die Methode entweder zurückgeben, z. B. ein HashSet, oder entfernen Sie die Duplikate nach der Rückgabe mit einer beliebigen Methode.
quelle
Hier ist ein guter Artikel, der drei Algorithmen zum Finden aller Permutationen behandelt, einschließlich eines zum Finden der nächsten Permutation.
http://www.cut-the-knot.org/do_you_know/AllPerm.shtml
C ++ und Python verfügen über integrierte Funktionen next_permutation und itertools.permutations .
quelle
Hier ist eine rein funktionale F # -Implementierung:
Die Leistung kann erheblich verbessert werden, indem der Swap geändert wird, um die veränderliche Natur von CLR-Arrays zu nutzen. Diese Implementierung ist jedoch in Bezug auf das Quellarray threadsicher und kann in einigen Kontexten wünschenswert sein. Bei Arrays mit mehr als 16 Elementen muss int durch Typen mit größerer / beliebiger Genauigkeit ersetzt werden, da Fakultät 17 zu einem int32-Überlauf führt.
quelle
Hier ist eine einfache Lösung in c # mit Rekursion:
quelle
Hier ist eine leicht verständliche Permutationsfunktion für String und Integer als Eingabe. Hiermit können Sie sogar Ihre Ausgabelänge einstellen (die im Normalfall der Eingabelänge entspricht).
String
und für Integer ändern Sie einfach die Aufrufermethode und MakePermutations () bleibt unberührt:
Beispiel 1: GetAllPermutations ("abc", 3); "abc" "acb" "bac" "bca" "cab" "cba"
Beispiel 2: GetAllPermutations ("abcd", 2); "ab" ac "" ad "" ba "" bc "" bd "" ca "" cb "" cd "" da "" db "" dc "
Beispiel 3: GetAllPermutations (486,2); 48 46 84 86 64 68
quelle
Hier ist die Funktion, die alle Permutationen druckt. Diese Funktion implementiert die von Peter erklärte Logik.
quelle
Das Folgende ist meine Implementierung der Permutation. Kümmere dich nicht um die Variablennamen, da ich es zum Spaß gemacht habe :)
quelle
Hier ist ein Beispiel auf hoher Ebene, das ich geschrieben habe und das die Erklärung der menschlichen Sprache veranschaulicht, die Peter gegeben hat:
quelle
Wenn Leistung und Speicher ein Problem sind, empfehle ich diese sehr effiziente Implementierung. Nach dem Heap-Algorithmus in Wikipedia sollte es der schnellste sein. Hoffe es passt zu deinem Bedürfnis :-)!
Nur zum Vergleich mit einer Linq-Implementierung für 10! (Code enthalten):
Linq: 36288000 Artikel in 50051 Millisekunden
quelle
Hier ist meine Lösung in JavaScript (NodeJS). Die Hauptidee ist, dass wir jeweils ein Element nehmen, es aus der Zeichenfolge "entfernen", den Rest der Zeichen variieren und das Element vorne einfügen.
Und hier sind die Tests:
quelle
Hier ist die einfachste Lösung, die ich mir vorstellen kann:
Die
distribute
Funktion verwendet ein neues Elemente
und einen
-Element-Liste und gibt eine Liste vonn+1
Listen zurück, die jeweilse
an einer anderen Stelle eingefügt wurden. Beispiel: Einfügen10
an jeder der vier möglichen Stellen in der Liste[1;2;3]
:Die
permute
Funktion faltet sich nacheinander über jedes Element und verteilt sich auf die bisher akkumulierten Permutationen, die in allen Permutationen gipfeln. Zum Beispiel die 6 Permutationen der Liste[1;2;3]
:Das Ändern von
fold
auf ascan
, um die Zwischenakkumulatoren beizubehalten, gibt Aufschluss darüber, wie die Permutationen jeweils für ein Element erzeugt werden:quelle
Listet Permutationen einer Zeichenfolge auf. Vermeidet Doppelarbeit, wenn Zeichen wiederholt werden:
quelle
Aufbauend auf der Lösung von @ Peter finden Sie hier eine Version, die eine einfache
Permutations()
Erweiterungsmethode im LINQ-Stil deklariert , die für alle funktioniertIEnumerable<T>
.Verwendung (Beispiel für Zeichenfolgen):
Ausgänge:
Oder auf einem anderen Sammlungstyp:
Ausgänge:
quelle
Hier ist die Funktion, die alle Permutationen rekursiv druckt.
quelle
quelle
Hier ist eine C # -Antwort, die etwas vereinfacht ist.
Ausgabe:
quelle
Dies ist meine Lösung, die für mich leicht zu verstehen ist
quelle
Hier ist noch eine Implementierung des erwähnten Algo.
quelle
new Permutation().GenerateFor("aba")
Ausgängestring[4] { "ab", "baa", "baa", "ab" }
quelle
quelle