Erhalt einer powerset von einem Satz in Java
Das powerset von {1, 2, 3}
ist:
{{}, {2}, {3}, {2, 3}, {1, 2}, {1, 3}, {1, 2, 3}, {1}}
Sagen wir, ich habe eine Set
in Java:
Set<Integer> mySet = new HashSet<Integer>();
mySet.add(1);
mySet.add(2);
mySet.add(3);
Set<Set<Integer>> powerSet = getPowerset(mySet);
Wie Schreibe ich die Funktion getPowerset, mit den besten möglich, um der Komplexität?
(Ich denke, es könnte sein, O(2^n).)
InformationsquelleAutor der Frage Manuel Aráoz | 2009-11-03
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ja, es ist
O(2^n)
ja, da müssen Sie zu generieren, sowie,2^n
möglichen Kombinationen. Hier ist eine funktionierende Implementierung, die Verwendung von Generika und sets:Und ein test, da dein Beispiel Eingabe:
InformationsquelleAutor der Antwort João Silva
Tatsächlich, ich habe code geschrieben, der das tut, was Sie für Fragen in O(1). Die Frage ist, was Sie planen, zu tun mit dem Set weiter. Wenn Sie nur anrufen würde
size()
darauf, dass der O(1), aber wenn du gehst, um es Durchlaufen, das ist offensichtlichO(2^n)
.contains()
wäreO(n)
usw.Brauchen Sie wirklich?
EDIT:
Dieser code ist jetzt erhältlich in Guaveausgesetzt durch die Methode
Setzt.powerSet(set)
.InformationsquelleAutor der Antwort Kevin Bourrillion
Hier ist eine Lösung, wo ich einen generator, der Vorteil, die gesamte Potenzmenge gespeichert nie auf einmal... So dass Sie können Durchlaufen Sie one-by-one, ohne dass es im Fehlerspeicher abgelegt werden. Möchte ich glaube, es ist eine bessere option... Hinweis: die Komplexität ist die gleiche, O(2^n), aber die Anforderungen an den Arbeitsspeicher reduziert werden (vorausgesetzt, dass der garbage collector verhält! 😉 )
Ihn nennen, verwenden Sie dieses Muster:
Es ist aus meiner Projekt-Euler-Bibliothek... 🙂
InformationsquelleAutor der Antwort st0le
Wenn n < 63, das ist eine vernünftige Annahme, da würden Sie run out of memory " (es sei denn Sie verwenden einen iterator-Implementierung) versuchen zu konstruieren, der Satz macht eh einen kürzeren Weg, es zu tun. Binäre Operationen sind viel schneller als
Math.pow()
und arrays für die Masken, aber irgendwie Java-Benutzer fürchten sich vor Ihnen...InformationsquelleAutor der Antwort Andrew Mao
Hier ist ein tutorial beschreibt genau, was Sie wollen, einschließlich der code. Sie sind richtig, dass die Komplexität ist O(2^n).
InformationsquelleAutor der Antwort Adamski
Kam ich mit einer anderen Lösung auf Basis von @Harry Er seine Ideen. Wahrscheinlich nicht die eleganteste, aber hier geht es so wie ich es verstehe:
Nehmen wir das klassische einfache Beispiel PowerSet von S P(S) = {{1},{2},{3}}.
Wir kennen die Formel, um die Anzahl der Teilmengen ist 2^n (7 + leere Menge).
Für dieses Beispiel 2^3 = 8 Teilmengen.
In um finden jede Teilmenge, die wir brauchen, um zu konvertieren 0-7 dezimal-zu-Binär-Darstellung gezeigt, in der umrechnungstabelle unten:
Wenn wir durchqueren die Tabelle zeilenweise, jede Zeile wird das Ergebnis in einer Untergruppe und die Werte, die jeder Teilmenge wird aus der aktivierten bits.
Jede Spalte in der Bin-Wert Abschnitt entspricht der Indexposition in der original-input-Set.
Hier mein code:
InformationsquelleAutor der Antwort Adolfo Perez
Wenn Sie Eclipse-Sammlungen (ehemals GS Collections), können Sie die
powerSet()
Methode auf alle SetIterables.Hinweis: ich bin committer für Eclipse Sammlungen.
InformationsquelleAutor der Antwort Craig P. Motlin
Ich war auf der Suche für eine Lösung, die war nicht so riesig wie die, die hier gepostet. Diese Ziele Java 7, so wird es erforderlich eine Handvoll von Pasten für die Versionen 5 und 6.
Hier einige Beispiel-code zum testen:
InformationsquelleAutor der Antwort Ben
Folgende Lösung ist entlehnt aus meinem Buch "Coding Interviews: Questions, Analysis & Lösungen":
Einige ganze zahlen in einem array ausgewählt werden, aus denen eine Kombination. Eine Reihe von bits verwendet wird, wobei jedes bit steht für eine ganze Zahl im array. Wenn die i-TEN Zeichen ausgewählt, die für eine Kombination, die i-TEN bit 1 ist, andernfalls ist es 0. Zum Beispiel drei bits werden verwendet für Kombinationen von array [1, 2, 3]. Wenn die ersten zwei Ganzzahlen 1 und 2 ausgewählt sind, zu verfassen eine Kombination [1, 2], die entsprechenden bits sind {1, 1, 0}. Ebenso bits entspricht einer anderen Kombination [1, 3] {1, 0, 1}. Wir sind in der Lage, alle Kombinationen eines Arrays mit Länge n wenn wir alle möglichen Kombinationen von n bits.
Einer Zahl aus einem Satz von bits. Alle möglichen Kombinationen von n bits entsprechen zahlen
von 1 zu 2^n-1. Daher, jede Zahl im Bereich zwischen 1 und 2^n-1 entspricht einer Kombination aus einem array mit Länge n. Zum Beispiel die Zahl 6 besteht aus bits {1, 1, 0}, so dass die ersten und zweiten Zeichen ausgewählt, die in das array [1, 2, 3] zu generieren, die Kombination [1, 2]. Ebenso die Zahl 5 mit bits {1, 0, 1} entspricht der Kombination [1, 3].
Den Java-code zur Implementierung dieser Lösung sieht wie folgt aus:
Die Methode increment-erhöht eine Zahl repräsentiert, die in einem Satz von bits. Der Algorithmus löscht 1-bits
aus dem niedrigstwertigen bit, bis ein 0-bit gefunden wird. Es setzt dann die am weitesten rechts liegenden bit 0 auf 1. Zum Beispiel, um zu erhöhen die Zahl 5 mit bits {1, 0, 1}, löscht es 1-bits von der rechten Seite und legt den niedrigstwertigen bit 0 auf 1. Die bits zu {1, 1, 0} für die Zahl 6, das ist das Resultat, dass 5 von 1.
InformationsquelleAutor der Antwort Harry He
Einige der oben genannten Lösungen leiden, wenn die Größe der groß ist, weil Sie schaffen eine Menge von Objekt-Müll gesammelt werden und benötigen die Daten kopieren. Wie können wir es vermeiden? Wir können die Tatsache nutzen, dass wir wissen, wie groß das Ergebnis gesetzt, wird die Größe (2^n), preallocate ein array, das groß, und fügen Sie einfach das Ende der es nie kopieren.
Der speedup wächst schnell mit n an. Ich verglich es mit João Silva Lösung vor. Auf meinem Rechner (alle Messungen ungefähr), n=13 ist 5x schneller, n=14 7x, n=15 ist 12-Fach, n=16 ist 25x, n=17 ist, 75x, n=18 ist 140x. So, dass der Müll für die Erstellung/Erfassung und kopieren dominiert, die ansonsten ähnlich zu sein scheinen big-O-Lösungen.
Preallocating das array am Anfang scheint zu sein, ein gewinnen im Vergleich zu lassen ihn wachsen dynamisch. Mit n=18, dynamisch wachsende dauert etwa doppelt so lange insgesamt.
InformationsquelleAutor der Antwort George Fairbanks
Hier ist ein einfacher iterativer O(2^n) Lösung:
InformationsquelleAutor der Antwort jump3r
InformationsquelleAutor der Antwort Bax
Wenn S eine endliche Menge mit N Elementen, dann ist die Potenzmenge von S enthält 2^N Elemente. Die Zeit, einfach aufzählen der Elemente der powerset ist 2^N, also
O(2^N)
ist eine untere Schranke für die Zeitkomplexität von (eifrig) Bau der powerset.Einfach ausgedrückt, alle Berechnungen, die umfasst das erstellen powersets ist nicht Maßstab für große Werte von N. Kein ausgeklügelter Algorithmus wird Ihnen helfen, ... mal abgesehen davon dass die Notwendigkeit zu erstellen, die powersets!
InformationsquelleAutor der Antwort Stephen C
Einer Weise, die ohne Rekursion die folgenden: Verwenden Sie eine binäre Maske und stellen Sie alle möglichen Kombinationen.
InformationsquelleAutor der Antwort Orestis
Dies ist meine rekursive Lösung, kann man die Potenzmenge jeder Satz mit Java-Generics. Seine Grundidee besteht in der Kombination der Kopf des Eingabe-array mit allen möglichen Lösungen, der rest der array wie folgt.
Dieser Ausgabe:
InformationsquelleAutor der Antwort Hazem Saleh
Dies ist mein Ansatz mit lambdas.
Oder parallel (siehe parallel - () - Kommentar):
Größe der input-set: 18
Logische Prozessoren: 8 à 3,4 GHz
Performance-Verbesserung: 30%
InformationsquelleAutor der Antwort Werner
Einem sub-Satz von t ist jeder Satz, die gemacht werden können durch das entfernen von null oder mehr Elementen von t ist. Die withoutFirst Teilmenge fügt hinzu, die Teilmengen von t sind, fehlt das erste element und die for-Schleife wird sich mit der Zugabe von Teilmengen mit dem ersten element. Zum Beispiel, wenn t enthaltenen Elemente ["1", "2", "3"], missingFirst wird, fügen Sie [[""],
["2"], ["3"], ["2","3"]] und die for-Schleife stick wird die "1" vor diesen-element und fügen Sie es in die newSet. So werden wir am Ende mit [[""], ["1"], ["2"], ["3"], ["1", "2"], ["1", "3"], ["2","3"], ["1", "2", "3"]].
InformationsquelleAutor der Antwort Hassan Alhujhoj
InformationsquelleAutor der Antwort Neyyadupakkam Sundarasekaran
Vor kurzem hatte ich Sie etwas wie dies, allerdings benötigt die kleinste Teillisten (mit 1 element, 2 Elemente, ...). Ich wollte nicht gehören das leere, noch die ganze Liste.
Auch habe ich nicht benötigen eine Liste aller Teillisten zurück, ich brauchte nur etwas mit jedem.
Wollte, dies zu tun, ohne Rekursion, und kam mit der folgenden (mit dem "Zeug" abstrahiert, in eine funktionale Schnittstelle):
In dieser Weise, ist es auch leicht zu einer Beschränkung auf die Teillisten der Längen.
InformationsquelleAutor der Antwort tijmen
Anderen Beispiel-Implementierung:
InformationsquelleAutor der Antwort Sandeep
InformationsquelleAutor der Antwort Selim Ekizoglu
Noch eine andere Lösung - mit java8+ streaming-api
Es ist faul und bestellt werden, so gibt es richtige Teilmengen, wenn es verwendet wird, mit "limit()".
- Und der client-code ist
/* Drucke : [][a][b][c][d][e][a, b][a, c][b, c] */
InformationsquelleAutor der Antwort ekobir
Könnten wir schreiben, die Kraft einstellen, mit oder ohne Verwendung von Rekursion. Hier ist ein Versuch, ohne Rekursion:
InformationsquelleAutor der Antwort YuVi
Hier ist zum erzeugen einer Kraft gesetzt. Die Idee ist erste =
S[0]
und kleinere Gruppen werdenS[1,...n]
.Berechnen Sie alle Untergruppen von smallerSet und setzen Sie Sie in allsubsets.
Für die einzelnen Teilmengen in allsubsets, duplizieren Sie es und fügen Sie zuerst die Teilmenge.
InformationsquelleAutor der Antwort None