Ich suche nach einer Datenstruktur zum Speichern einer Menge, so dass bei zwei Instanzen der Größe denen bekannt ist, dass sie einen nicht leeren Schnittpunkt haben, das minimale Element des Schnittpunkts in der Zeit kann. Ist dies entweder im schlimmsten Fall oder bei amortisierter Komplexität möglich? Weitere Anforderungen an die Datenstruktur: -Löschung, -Initialisierung.
Hier ist eine beispielhafte Anwendung einer solchen Datenstruktur, um die Anforderungen zu klären. Die Eingabe besteht aus n Teilmengen von alle die Nummer n enthalten. Die Ausgabe ist eine n x n-Matrix, deren Eintrag das minimale Element im Schnittpunkt der Mengen i und j ist. Mit einem grundlegenden Ansatz kann man dieses Problem in -Zeit lösen . Mit einer Datenstruktur, die die obigen Bedingungen erfüllt, könnte man sie in Zeit lösen .
quelle
Antworten:
Das kannst du nicht. Es gibt keine solche Datenstruktur. Angenommen, Sie haben eine separate Instanz pro Satz und jede Instanz wird separat initialisiert (wobei nur Informationen zu dem Satz verwendet werden, den sie darstellt, und keine Informationen zu den anderen Sätzen), sind diese Laufzeiten nicht erreichbar.
Insbesondere wenn Sie zwei Sätze haben, dauert das Finden des minimalen gemeinsamen Elements Zeit. In der Tat erfordert das Testen der Disjunktheit -Zeit, wie hier erläutert . Stellen Sie sich nun vor, Sie beginnen mit zwei Mengen über dem Universum . Sei und . Jetzt haben garantiert ein gemeinsames Element. Wenn Sie also eine gute Datenstruktur für Ihr Problem hatten, speichern Sie in einer Instanz der Datenstruktur und in einer anderen. Wenn wir dann eine Möglichkeit hätten, das minimale Element von in zu findenΩ(n) Ω(n) S1,S2 {1,2,…,n−1} T1=S1∪{n} T2=S2∪{n} T1,T2 T1 T2 T1∩T2 o(n) Zeit, dies würde uns eine Möglichkeit geben, die Disjunktheit von in Zeit zu testen (testen Sie einfach, ob das minimale Element kleiner als ) - aber wir wissen bereits, dass letzteres nicht möglich ist. Daraus folgt, dass Ersteres auch nicht möglich ist, dh, dass eine Datenstruktur für Ihr Problem Zeit benötigt, um das minimale gemeinsame Element von zwei Mengen zu finden.S1,S2 o(n) n Ω(n)
Dies bedeutet nicht, dass Ihre Anwendung nicht effizient gelöst werden kann. Es könnte immer noch eine Möglichkeit geben, Ihre Anwendung in Zeit zu lösen . Dieses Ergebnis schließt das nicht aus.O(n2logn)
quelle
Hier ist eine Idee, um das Problem zu lösen, wenn 2 Sätze gegeben sind:
Sie können "Sets" an einem rot-schwarzen Baum halten. Zusätzlich ordnen wir für jeden Knoten im Baum ein Bit zu, um zu bestimmen, ob sein Teilbaum in beiden Mengen ein Element enthält. Zur Darstellung wird es als Einfügebit bezeichnet . Ich gehe davon aus, dass der rot-schwarze Baum die Elemente von links nach rechts sortiert.
Beim Einfügen eines Elements in den Baum prüft der Algorithmus, ob das Element im Baum vorhanden ist (dh in dem anderen die Menge). Wenn nicht, fügen wir das Element wie gewohnt ein. Wenn nicht, schaltet der Algorithmus das Einfügebit der entsprechenden Knoten ein, indem er von der Wurzel zu dem Blatt wandert, das das Element enthält. Im schlimmsten Fall dauert es .O(logn)
Beim Löschen eines Elements prüft der Algorithmus, ob das Element im Baum vorhanden ist und ob das Einfügebit aktiviert ist. Wenn das Element nicht im Baum vorhanden ist, geben wir einen Fehler zurück. Wenn das Element vorhanden ist und das Einfügebit deaktiviert ist, löschen wir das Element wie im Rot-Schwarz-Baum-Algorithmus. Andernfalls schaltet der Algorithmus das Einfügebit der entsprechenden Knoten aus, indem er von der Wurzel zu dem Blatt wandert, das das Element enthält. Das Löschen dauert .O(logn)
Schließlich beginnt der Algorithmus zum Finden eines minimalen Elements, das von beiden Sätzen gemeinsam genutzt wird, mit der Wurzel. Wenn das Einfügebit der Wurzel ausgeschaltet ist, werden die Mengen getrennt, und der Algorithmus gibt einen Fehler zurück. Andernfalls wandert der Algorithmus rekursiv zum linken Kind, wenn sein Einfügebit aktiviert ist, und andernfalls zum rechten Kind. Der Algorithmus stoppt beim Element mit dem Minimalwert. Der Algorithmus läuft bei .O(logn)
Ich versuche zu überlegen, wie man das für eine größere Anzahl von Sätzen verallgemeinert ...
quelle
Initialisieren:
1) Erstellen Sie einen rot-schwarzen Baum, der alle Elemente der Liste Nr. 1 - O (n log n) für die gesamte Liste enthält.
2) Durchlaufen Sie alle Elemente der Liste Nr. 2 und prüfen Sie, ob sie im rot-schwarzen Baum vorhanden sind - O (n log n) für die gesamte Liste.
3) Wenn sie im rot-schwarzen Baum vorhanden sind, fügen Sie dieses Element aus der Liste ein # 2 in Ihren Lieblings-Min-Heap - O (n log n) für die gesamte Liste
Um dann nach dem sich überschneidenden Element zu suchen, schauen Sie einfach oben auf den Heap, das ist also O (1).
quelle