Wie würde eine Implementierung eines Algorithmus in Java aussehen, um den Median zu berechnen?
Für eine Karte, wo der Schlüssel eine Nummer einer Sequenz darstellt und der Wert wie oft diese Zahl in der Sequenz erschienZum Beispiel:
%Vor%in einer Karte:
%Vor%würde ergeben:
%Vor% Also, was ich suche, ist eine Java-Implementierung von calculateMedian
.
Guava :
%Vor%Nun ist die Antwort auf Ihre Frage:
%Vor%Wirklich. Das ist es. (Oder überprüfen Sie, ob die Größe gerade ist und mitteln Sie die zwei zentralen Werte, um genau zu sein.)
Wenn die Anzahl besonders groß ist, wäre es schneller, das entrySet
des Multisets zu verwenden und eine laufende Summe zu behalten, aber der einfachste Weg ist normalerweise gut.
Lineare Zeit
Wenn Sie die Gesamtzahl der Zahlen kennen (in Ihrem Fall ist es 16), können Sie vom Anfang oder vom Ende der Karte gehen und die Zählungen aufsummieren, bis Sie zum runden (n / 2) ten Element kommen, oder für den Fall, dass die Summe sogar im Durchschnitt von Boden (n / 2) th und ceil (n / 2) th Elementen = Median .
Wenn Sie die Gesamtzählung nicht kennen, müssen Sie sie mindestens einmal durchlaufen.
Sublineare Zeit
Wenn Sie sich für die Datenstruktur entscheiden und eine Vorverarbeitung vornehmen können, sehen Sie sich die Wikipedia auf Auswahlalgorithmus an sogar ein sublinearer Algorithmus. Sie können die sublineare Zeit auch erhalten, wenn Sie etwas über die Verteilung der Daten wissen.
BEARBEITEN: Also unter der Annahme, dass wir eine Sequenz mit Zählungen haben, was wir tun können, ist
key -> count
wird eine andere Karte beibehalten - key -> running_total
Dies verdoppelt die Speicherbelegung, ergibt aber O (log n) für Median und O (1) für total_count.
SortedMap
, d. h. a TreeMap
Für einen einfachen aber vielleicht nicht so effizienten Algorithmus würde ich es so machen:
1. Erweitern Sie die Karte zu einer Liste.
praktisch gesprochen: Iterieren Sie die Karte und fügen Sie der neuen Liste den Schlüssel 'value-times' hinzu. Zum Schluss die Liste sortieren.
%Vor%2. Berechne den Median
Jetzt müssen Sie eine Methode int calculateMedian(List<Integer> sorted)
implementieren. Dies hängt von der Art des Median ab, den Sie benötigen. Wenn es sich nur um den Stichprobenmedian handelt, ist das Ergebnis entweder der mittlere Wert (für Listen mit einer ungeraden Anzahl von Elementen) oder der Durchschnitt der beiden mittleren Werte (für Listen mit einer geraden Länge). Beachten Sie, dass die Liste sortiert werden muss!
(Ref: Sample Median / wikipedia )
OK, OK, obwohl Chris die Effizienz nicht erwähnt hat, hier ist eine Idee, wie man den Stichprobenmittelwert (!) berechnet, ohne die Karte zu erweitern ...
%Vor%(Ich habe keinen Compiler zur Hand - wenn es zu viele Syntaxfehler hat, behandle es bitte als Pseudocode;))