Ich muss den laufenden Median berechnen:
Eingabe: , , Vektor .
Ausgabe: Vektor , wobei der Median von .
(Kein Schummeln mit Näherungen; ich hätte gerne genaue Lösungen. Elemente sind große ganze Zahlen.)
Es gibt einen einfachen Algorithmus, der einen Suchbaum der Größe . Die Gesamtlaufzeit beträgt O ( n log k ) . (Hier bezieht sich ein "Suchbaum" auf eine effiziente Datenstruktur, die Einfügungen, Löschungen und mittlere Abfragen in logarithmischer Zeit unterstützt.)
Das kommt mir allerdings etwas blöd vor. Wir werden effektiv alle Ordnungsstatistiken in allen Fenstern der Größe lernen , nicht nur die Mediane. Darüber hinaus ist dies in der Praxis nicht allzu attraktiv, insbesondere wenn k groß ist (große Suchbäume sind in der Regel langsam, der Overhead beim Speicherverbrauch ist nicht trivial, die Cache-Effizienz ist oft schlecht usw.).
Können wir etwas wesentlich besser machen?
Gibt es Untergrenzen (z. B. ist der Trivialalgorithmus für das Vergleichsmodell asymptotisch optimal)?
Edit: David Eppstein gab eine schöne Untergrenze für das Vergleichsmodell! Ich frage mich, ob es trotzdem möglich ist, etwas Klügeres als den trivialen Algorithmus zu tun.
Könnten wir zum Beispiel etwas in diese Richtung tun: Teilen Sie den Eingabevektor in Teile der Größe ; sortiere jeden Teil (verfolge die ursprünglichen Positionen jedes Elements); und dann den stückweise sortierten Vektor verwenden, um die laufenden Mediane ohne zusätzliche Datenstrukturen effizient zu finden? Natürlich wäre dies immer noch O ( n log k ) , aber in der Praxis ist das Sortieren von Arrays in der Regel viel schneller als das Verwalten von Suchbäumen.
Bearbeiten 2: Saeed wollte einige Gründe sehen, warum das Sortieren meiner Meinung nach schneller ist als Suchbaumoperationen. Hier sind sehr schnelle Benchmarks für , n = 10 8 :
- ≈ 8s: Sortieren von Vektoren mit jeweils k Elementen
- ≈ 10s: Sortierung eines Vektors mit Elementen
- ≈ 80s: Einfügungen und Löschungen in einer Hash-Tabelle der Größe k
- ≈ 390s: Einfügungen und Löschungen in einem ausgeglichenen Suchbaum der Größe k
Die Hash-Tabelle dient nur zum Vergleich. Es ist in dieser Anwendung nicht direkt von Nutzen.
Zusammenfassend lässt sich sagen, dass sich die Sortierleistung im Vergleich zu ausgeglichenen Suchbaumoperationen um fast den Faktor 50 unterscheidet. Und es wird noch schlimmer, wenn wir erhöhen .
(Technische Details: Daten = zufällige 32-Bit-Ganzzahlen. Computer = ein typischer moderner Laptop. Der Testcode wurde in C ++ unter Verwendung der Standard-Bibliotheksroutinen (std :: sort) und Datenstrukturen (std :: multiset, std :: unsorted_multiset). Ich habe zwei verschiedene C ++ - Compiler (GCC und Clang) und zwei verschiedene Implementierungen der Standardbibliothek (libstdc ++ und libc ++) verwendet. Traditionell wurde std :: multiset als hochoptimierter Rot-Schwarz-Baum implementiert.)
quelle
Antworten:
Hier ist eine Untergrenze für das Sortieren. Erstellen Sie für einen zu sortierenden Eingabesatz der Länge n eine Eingabe für Ihr laufendes Medianproblem, die aus n - 1 Kopien einer Zahl kleiner als das Minimum von S , dann aus S selbst und dann aus n - 1 Kopien einer Zahl größer als besteht das Maximum von S und setze k = 2 n - 1 . Die laufenden Mediane dieser Eingabe stimmen mit der sortierten Reihenfolge von S überein .S n n−1 S S n−1 S k=2n−1 S
Also in einem Vergleichsmodell der Berechnung, Zeit erforderlich. Wenn es sich bei Ihren Eingaben möglicherweise um Ganzzahlen handelt und Sie Ganzzahl-Sortieralgorithmen verwenden, können Sie dies besser tun.Ω(nlogn)
quelle
Bearbeiten: Dieser Algorithmus wird jetzt hier vorgestellt: http://arxiv.org/abs/1406.1717
Ja, um dieses Problem zu lösen, ist es ausreichend, die folgenden Vorgänge auszuführen:
Grob gesagt lautet die Idee:
Für jedes :i
Die verknüpften Listen sind nur Element-Arrays von Indizes, daher sind sie leichtgewichtig (mit der Ausnahme, dass die Lokalität des Speicherzugriffs schlecht ist).k
Hier ist eine Beispielimplementierung und Benchmarks:
Hier ist eine Darstellung der Laufzeiten (für ):n≈2⋅106
quelle
In Anbetracht von Davids Grenzen ist es unwahrscheinlich, dass Sie einen besseren Worst-Case-Fall erzielen können, aber es gibt bessere ausgangssensitive Algorithmen. Insbesondere wenn in der Anzahl der Mediane im Ergebnis ist, können wir das Problem in der Zeit O ( n log m + m log n ) lösen .m O(nlogm+mlogn)
quelle