Come minimo, avrete bisogno di mantenere una coda delle più recenti 1000 elementi.
Per mantenere una media corrente, mantenere un totale parziale degli ultimi 1000 elementi; quando aggiungi un nuovo elemento alla coda, aggiungi il suo valore al totale e sottrai anche il valore dell'elemento più vecchio che hai appena rimosso dalla coda. Restituisci il totale diviso per 1000 e lì vai.
Per mantenere un N ° percentile in esecuzione, mantenere due heap e mantenere un conteggio degli elementi negli heap; l'heap "inferiore" ha il N% inferiore dei valori e l'heap "superiore" ha il valore superiore (1-N)% (ad esempio, l'heap del 95 ° percentile inferiore avrà 950 elementi e l'heap del 5 ° percentile superiore sarà avere 50 elementi). In qualsiasi momento puoi restituire l'elemento più basso dall'heap superiore, e questo è il tuo percentile. Quando rimuovi un elemento dalla coda dei valori recenti, rimuovi anche il valore dagli heap. Se questo lascia gli heap non bilanciati (ad esempio l'heap inferiore ha 951 elementi e l'heap superiore ha 49 elementi), quindi sposta gli elementi per bilanciarli (ad esempio rimuovi l'elemento superiore dall'heap inferiore e lo aggiunge all'heap superiore).
Poiché si desiderano due percentili, utilizzare tre heap: l'heap inferiore ha i 950 elementi inferiori, il centro ha i successivi 40 e quello superiore ha i 10 più alti. Restituisce l'elemento più basso dell'heap centrale per il 95 ° percentile e l'elemento più basso dell'heap superiore per il 99 ° percentile.
L'aggiunta e la rimozione di elementi heap è O (lg (n)), quindi è il costo dell'aggiunta di un nuovo elemento alla coda e tre heap: rimuovere l'elemento di coda più vecchio dagli heap (O (lg (n)), aggiungi il nuovo elemento di coda all'heap appropriato (O (lg (n)) e bilancia gli heap se necessario (di nuovo, O (lg (n)). Aggiungi il nuovo elemento all'heap più basso il cui elemento più alto è maggiore l'elemento mucchio, vale a dire
if (newElement < lowestHeap.maxElement) {
lowestHeap.add(newElement)
} else if (newElement < middleHeap.maxElement) {
middleHeap.add(newElement)
} else {
highestHeap.add(newElement)
}
assicurarsi che le cumuli consentono elementi duplicati
fonte
2013-05-08 23:19:37
Penso che sia possibile mantenere una matrice di 1000 voci senza troppi problemi o penalità di memoria. Il problema è l'ordinamento dei dati (è necessario ordinarlo se si vuole ottenere il percentile, penso) – Barranka
ya, l'ordinamento è la parte che potrebbe causare più problemi – jamesatha
Non penso che ci sia un modo per calcola uno qualsiasi dei percentili se non trattiene i dati in un array, quindi l'algoritmo (come penso dovrebbe essere) è: 1. Memorizza i dati; 2. Ordina i dati (con il tuo metodo preferito); 3. Ottieni il valore nella posizione desiderata ('array [n]' dove 'n = round (array.length * p)' e '0 <= p <= 1'). – Barranka