Su finestre di dimensioni inferiori, l' n log n
ordinamento potrebbe funzionare. Ci sono algoritmi migliori per raggiungere questo obiettivo?
Su finestre di dimensioni inferiori, l' n log n
ordinamento potrebbe funzionare. Ci sono algoritmi migliori per raggiungere questo obiettivo?
Risposte:
Ecco un articolo che descrive un possibile algoritmo. Codice sorgente incluso e un'applicazione abbastanza seria (rilevamento dell'onda gravitazionale basata sull'interferometria laser), quindi puoi aspettarti che sia ben testato.
Se sei disposto a tollerare un'approssimazione, esistono altri metodi. Ad esempio, un'approssimazione è un valore il cui rango è entro una certa distanza (specificata dall'utente) dalla mediana reale. Ad esempio, la mediana ha un rango (normalizzato) 0,5 e se si specifica un termine di errore del 10%, si desidera una risposta con rango compreso tra 0,45 e 0,55.
Se tale risposta è appropriata, allora ci sono molte soluzioni che possono funzionare su finestre scorrevoli di dati. L'idea di base è quella di mantenere un campione dei dati di una certa dimensione (circa 1 / termine di errore) e calcolare la mediana su questo campione. Si può dimostrare che con alta probabilità, indipendentemente dalla natura dell'input, la mediana risultante soddisfa le proprietà che ho menzionato sopra.
Pertanto, la domanda principale è come mantenere un campione corrente dei dati di una certa dimensione, e ci sono molti approcci per questo, inclusa la tecnica nota come campionamento del serbatoio. Ad esempio, questo documento: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.24.7136
Se si mantiene una finestra di lunghezza-k di dati come un elenco doppiamente collegato, quindi, mediante una ricerca binaria (per inserire ogni nuovo elemento man mano che viene spostato nella finestra) e una matrice circolare di puntatori (per individuare immediatamente gli elementi che deve essere eliminato), ogni spostamento della finestra richiede uno sforzo O (log (k)) per l'inserimento di un elemento, solo uno sforzo O (1) per eliminare l'elemento spostato fuori dalla finestra e solo uno sforzo O (1) per trovare la mediana (perché ogni volta che un elemento viene inserito o eliminato nell'elenco è possibile aggiornare un puntatore alla mediana nel tempo O (1)). Lo sforzo totale per elaborare una matrice di lunghezza N è quindi O ((nk) log (k)) <= O (n log (k)). Questo è meglio di qualsiasi altro metodo proposto finora e non è un'approssimazione, è esatto.
Come hai detto, l'ordinamento sarebbe O(n·log n)
per una finestra di lunghezza n
. In questo modo si aggiunge un altro che l=vectorlength
rende il costo totale O(l·n·log n)
.
Il modo più semplice per farlo è mantenere un elenco ordinato degli ultimi n elementi in memoria quando si passa da una finestra a quella successiva. Poiché rimuovere / inserire un elemento da / in un elenco ordinato sono entrambi O(n)
ciò comporterebbe costi di O(l·n)
.
pseudocodice:
l = length(input)
aidvector = sort(input(1:n))
output(i) = aid(n/2)
for i = n+1:l
remove input(i-n) from aidvector
sort aid(n) into aidvector
output(i) = aid(n/2)
Ecco una soluzione O (1) per trovare la mediana corrente e O (log n) per aggiungere un nuovo numero http://www.dsalgo.com/RunningMedian.php
Se riesci a vivere con una stima anziché con la mediana reale, l' algoritmo Remedian (PDF) è un passaggio con requisiti di archiviazione bassi e precisione ben definita.
Il rimedio con base b procede calcolando le mediane dei gruppi di osservazioni b, quindi le mediane di queste mediane, fino a quando rimane una sola stima. Questo metodo richiede semplicemente k matrici di dimensione b (dove n = b ^ k) ...
Ho usato questa libreria C ++ di RunningStats in un'applicazione integrata. È la libreria di statistiche di corsa più semplice che abbia mai trovato.
Dal link:
Il codice è un'estensione del metodo di Knuth e Welford per calcolare la deviazione standard in un passaggio attraverso i dati. Calcola asimmetria e curtosi anche con un'interfaccia simile. Oltre a richiedere solo un passaggio tra i dati, l'algoritmo è numericamente stabile e preciso.