Dal mio commento originariamente: questo è strettamente correlato a una quantità onnipresente nella valutazione accademica della produttività, l'indice Hirsh, meglio noto come -indexh . In breve è definito come il numero di pubblicazioni si ha tale che ciascuno di essi presenta almeno h citazioni (il più grande tale h ).hhh
L'unico modo in cui il tuo problema differisce è che potresti essere interessato non solo a quante pubblicazioni soddisfano il criterio, ma anche a ciò che conta la loro citazione , ma questa è una banale modifica. I dati sono già lì, l'algoritmo originale li rilascia.
Il calcolo generalmente attuato è piuttosto semplice e concorda con la risposta di Karolis Juodelė .
Aggiornamento: a seconda della dimensione e del carattere dei dati, può valere la pena esplorare metodi che ordinano parzialmente l'array filtrando i dati sopra e sotto un punto cardine (mi viene in mente quicksort). Quindi, a seconda che ci sia troppo o troppo poco, regola il perno e ripeti sul sottoinsieme che lo contiene e così via. Non è necessario un ordine tra elementi superiori a , e certamente non tra quelli inferiori a quello. Ad esempio, una volta trovati tutti gli elementi maggiori o uguali a h 1 e ce ne sono meno di h 1 , non è necessario toccare nuovamente quel sottoinsieme, basta aggiungerlo. Questo converte la ricorsione inerente al quicksort in una ricorsione della coda e quindi può essere riscritta come un ciclo.hh1h1
Il mio Haskell è un po 'arrugginito ma questo dovrebbe fare quello che ho descritto sopra e sembra funzionare. Spero che possa essere compreso fino a un certo punto, sono felice di fornire ulteriori spiegazioni.
-- just a utility function
merge :: [a] -> [a] -> [a]
merge [] ys = ys
merge (x:xs) ys = x : merge xs ys
-- the actual implementation
topImpl :: [Int] -> [Int] -> [Int]
topImpl [] granted = granted
topImpl (x:xs) granted
| x == (1 + lGreater + lGranted) = x : merge greater granted
| x > (1 + lGreater + lGranted) = topImpl smaller (x : merge greater granted)
| otherwise = topImpl greater granted
where smaller = [y | y <- xs, y < x]
greater = [y | y <- xs, y >= x]
lGreater = length greater
lGranted = length granted
-- starting point is: top of whole array, granted is empty
top :: [Int] -> [Int]
top arr = topImpl arr []
L'idea è quella di raccogliere granted
ciò che sai parteciperà sicuramente al risultato e non ordinarlo ulteriormente. Se greater
insieme agli x
accoppiamenti, siamo fortunati, altrimenti dovremo provare con un sottoinsieme più piccolo. (Il perno x
è semplicemente quello che è accaduto per essere il primo elemento dell'elenco secondario che è attualmente considerato.) Notare che il vantaggio significativo rispetto al prendere elementi più grandi uno per uno è che lo facciamo su blocchi di dimensioni medie e non è necessario ordinarli ulteriormente.r e m a ining/2
Esempio:
Prendiamo il tuo set [1,3,4,1,3,6]
.
x = 1
, granted = []
, greater = [3,4,1,3,6]
. Ouch, abbiamo colpito un caso patologico quando il perno è troppo piccolo (in realtà così piccolo che smaller
è vuoto) proprio nel primo passo. Fortunatamente il nostro algo è pronto per questo. Scarta x
e riprova con greater
solo.
x = 3
, granted = []
, greater = [4,3,6]
. Insieme, formano un array di lunghezza 4, ma abbiamo solo un limite dal basso di 3, quindi è troppo. Ripeti da greater
solo.
x = 4
, granted = []
, greater = [6]
. Questo dà una matrice di 2 elementi ≥ 4 ciascuno, sembra che potremmo averne bisogno per alcuni di più. Continua e ripeti smaller = [3]
.
x = 3
, granted = [4,6]
, greater = []
. Questo insieme fornisce una matrice di 3 elementi ≥ 3 ciascuno, quindi abbiamo la nostra soluzione [3,4,6]
e possiamo tornare. (Si noti che la permutazione può variare a seconda dell'ordinamento dell'input, ma conterrà sempre i termini più alti possibili, mai [3,3,6]
o [3,3,4]
per il vostro esempio.)
(A proposito, si noti che la ricorsione in effetti è appena crollata in un ciclo.) La complessità è leggermente migliore di quicksort a causa dei molti confronti salvati:
n - 1
O ( logn )O ( n )
nO ( n2)
Ci sono alcuni confronti inutili nel codice sopra, come calcolare smaller
se ne abbiamo bisogno o no, possono essere facilmente rimossi. (Penso che la valutazione pigra se ne occuperà comunque.)