finden median in eine Feste Größe-verschieben-Fenster über eine lange Abfolge von Daten
Gegeben eine Sequenz von Daten (es kann Duplikate), eine Feste Größe verschieben
Fenster, verschieben Sie das Fenster bei jeder iteration aus dem Anfang der Daten
Sequenz, so dass
(1) die ältesten Daten element wird entfernt aus dem Fenster und eine neue Daten
element drückt man in die Fenster
(2) finden Sie den median der Daten innerhalb des Fensters bei jeder Bewegung.
Die folgenden Beiträge sind nicht hilfreich.
Effektiv zu finden, der Mittelwert einer zufälligen Reihenfolge
Datenverknüpfung auf Basis eines gleitenden Zeitfensters in R
Meine Idee:
Verwenden Sie 2 Haufen zu halten median. In der Seite, die das Fenster, Sortieren Sie die Daten in das Fenster
in der ersten iteration werden die min-heap-hält der größere Teil und die max-heap -
hält der kleinere Teil. Wenn das Fenster hat ungerade Anzahl von Daten, die max-heap -
gibt den median andernfalls das arithmetische Mittel der oberen Elemente der
zwei heaps ist der median.
Wenn eine neue Daten geschoben, um die Fenster, entfernen Sie die ältesten Daten von einem
der heap und vergleichen Sie die neuen Daten mit dem top-max und min-heap, so
dass zu entscheiden, welche heap die Daten gestellt werden. Suchen Sie dann den median nur
wie in der ersten iteration.
Aber, wie zu finden, ein Daten-element in einem heap ist ein problem. Heap ist ein binärer
Baum nicht eine binäre Suchbaum.
Ist es möglich, um es zu lösen mit O(n) oder O(n * lg m) wobei m die Größe des Fensters und
Platz: O(1) ?
Jede Hilfe wird wirklich geschätzt.
Dank
- Sind stackoverflow.com/questions/5527437/... oder stackoverflow.com/questions/1309263/... nützlich?
- Die neuesten Daten, die das nächste Element, oder gibt es einige andere Kriterien? Sind Sie der Verarbeitung dieser Elemente in einem first-in-first-out-Art und Weise?
- in jeder iteration werden die ältesten Daten gelöscht, die Fenster und eine neue Daten in das Fenster und suchen Sie dann den neuen median im Fenster. Für die ältesten Daten , es ist FIFO. Dank
- Ich glaube nicht, Platz O(1) möglich ist. Sie müssen speichern Sie den Inhalt des Fensters, so dass Sie nicht unter O(m).
- Wie Sie entfernen die ältesten Daten aus einem der Haufen ?
Du musst angemeldet sein, um einen Kommentar abzugeben.
O(n*lg m) ist einfach:
Nur pflegen Sie Ihre Fenster, wie zwei
std::set
s, eine für die untere Hälfte, eine für die Obere Hälfte. Einfügen eines neuen Elements Kosten O(lg m), zur Feststellung und Entfernung der alten-element kostet das gleiche. Die Bestimmung der median mithilfe der Methode, die Sie beschrieben, in Ihrer Frage kostet O(1).Wie Sie schieben Sie das Fenster über der Sequenz, in jeder iteration entfernen Sie das Element, Sturz aus dem Fenster (O(lg m)), fügen das neue Element ein (O(lg m)) und berechnen Sie den median (O(1)), was eine Gesamtanzahl von O(n lg m).
Diese Lösung verwendet Speicherplatz O(m), natürlich, aber ich glaube nicht, dass Sie Weg erhalten können, ohne speichern das Fenster Inhalt.
m/2 - 1
Elemente, und eine für die Oberem/2 - 1
Elemente, und speichern auch der median. Beim verschieben des Fensters über: 1. Entfernen Sie das alte element wird entweder in der unteren oder oberen Baum (O(log m)
), dann 2. Legen Sie das neue element in die untere - oder Obere-Baum, basierend auf, wenn es < oder > der median. Wenn einer der Bäume hat jetzt zu viele Elemente, entfernen Sie die größte (für das untere) oder kleinste (für den oberen) - element (O(log m)
), rufen, dass die neuen median, und legen Sie die alte median in der anderen Struktur (O(log m)
). InsgesamtO(log m)
O(1)
- halten Sie einfach einen Verweis zu Ihnen. C++'sstl::set
tut dies bereits, über*stl::set::rbegin()
<
dem Elternteil und dem Recht>
machen die linken<=
und das Recht>
. Jeder Knoten sollte immer noch zwei (oder weniger) Kinder.O(log m)
(m = Fenster-Größe) jeder Schritt, indem er das gesamte AlgorithmusO(n log m)
; siehe die Antwort und/oder meinen ersten Kommentar oben für Einzelheiten. Es kann ein Weg, um esO(1)
pro Schritt, aber wenn das so ist, weiß ich nicht, wie.O(m)
, aber ich könnte falsch sein.O(m)
ist der beste Speicherplatz-Komplexität. Es ist unmöglich, sich zu re-berechnen Sie den median, ohne zu halten Spur von alle der Werte. Sie könnten in der Lage sein, zu halten, zu zählen, wie viele von jeder Wert, aber dass nur noch reduziert zuO(p*m)
, wo p ist der Prozentsatz eindeutige Werte:numUnique/m
. Diese kann kleiner sein, für einige Daten, aber es ist immer noch O(m).Implementierte ich fast genau dem Algorithmus, den Sie hier beschreiben: http://ideone.com/8VVEa, und beschrieb es hier: Rolling median in C - Turlach Umsetzung
Den Weg, um die "find ältesten" problem ist, dass die Werte in einem Ringpuffer, so haben Sie immer einen Zeiger auf die ältesten. Was Sie store in der heap-Puffer-Indizes.
Also der Platzbedarf ist 2M, und jedes update ist O(lg M).
Gleiche Antwort wie hc_ aber statt mit einem stock BST verwenden Sie eine version, bei der jeder Knoten die Anzahl der Elemente im sub-Baum. Auf diese Weise finden median in O(log(m)).
Gab ich diese Antwort für den "rolling median C" - Frage
Konnte ich nicht finden, eine moderne Implementierung einer c++ - Datenstruktur mit order-Statistik so endete die Umsetzung der Ideen in top-Coder-link ( Match-Redaktion: nach unten scrollen, um FloatingMedian).
Zwei multimengen
Ersten Idee Partitionen die Daten in zwei Datenstrukturen (heaps, multimengen etc) mit O(ln N) pro einfügen/löschen nicht zulassen, dass die quantile zu dynamisch geändert werden, ohne große Kosten. I. e. wir haben eine rollende median, oder ein rolling-75%, aber nicht beides zur gleichen Zeit.
Segment-Baum
Die zweite Idee verwendet eine segment-Baum ist O(ln N) für einfügen/löschen/Abfragen, aber flexibler ist. Am besten von allen das "N" ist die Größe der Daten-Bereich. Also, wenn Sie Ihre Rollen median hat ein Fenster von einer million Elemente, aber Ihre Daten variiert von 1..65536, dann nur 16 Operationen sind erforderlich, die pro-Bewegung der rollenden Fenster von 1 million Euro!! (Und Sie müssen nur 65536 * sizeof(counting_type) bytes, z.B. 65536*4).
GNU Ordnung Statistik Bäumen
Kurz vor dem aufgeben fand ich, dass stdlibc++ enthält, um statistische Bäumen!!!
Diese zwei wichtigen Operationen:
Sehen libstdc++ - Handbuch policy_based_data_structures_test (Suche nach "split-and-join").
Ich gewickelt habe den Baum für die Verwendung in einem convenience-header für Compiler, die c++0x/c++11 Stil partiellen Typdefinitionen:
Lege ich meine segment-Baum (siehe meinen anderen post), das es erlaubt, die Frequenz-Verteilung der Zählungen sehr effizient abgefragt werden.
Diese implementiert die folgende Datenstruktur:
Jedes segment hält die Anzahl der Elemente in der Reihe, die es abdeckt.
Ich benutze 2N Segmente für einen Wertebereich von 1..N.
Diese befinden sich in einer einzigen ausgerollt Vektor anstatt die Baum-format zeigen bildlich vor.
Also, wenn Sie berechnen, die rolling gemittelt über eine Reihe von ganzen zahlen, die variieren von 1..65536, dann brauchen Sie nur 128kb zu speichern, und können die insert/delete/query mit O(ln N), wobei N = die Größe des Bereichs, d.h. 2**16 Operationen.
Dies ist ein großer Gewinn, wenn die Daten-Bandbreite ist viel kleiner als Ihre rollenden Fenster.