Do meu comentário originalmente: Isto está intimamente relacionado a uma onipresente quantidade na avaliação acadêmica produtividade, o índice Hirsh, mais conhecido como o -Indexh . Em suma, é definida como o número de publicações uma tem de tal modo que cada um deles tem pelo menos h citações (o maior tal h ).hhh
A única maneira de o seu problema diferir é que você estaria interessado não apenas em quantas publicações atendem ao critério, mas também em qual é a citação delas , mas essa é uma modificação trivial. Os dados já estão lá, o algoritmo original simplesmente os solta.
O cálculo geralmente implementado é bastante direto e concorda com a resposta de Karolis Juodelė .
Atualização: Dependendo do tamanho e do caráter dos seus dados, pode valer a pena explorar métodos que classificam parcialmente a matriz, filtrando os dados acima e abaixo de um ponto crucial (o quicksort vem à mente). Então, dependendo se há muito pouco ou muitos, ajuste o pivô e refaça o subconjunto que o contém e assim por diante. Você não precisa de uma ordem entre elementos maiores que , e certamente não entre aqueles inferiores a isso. Por exemplo, quando você encontrar todos os elementos maiores ou iguais a h 1 e houver menos de h 1 deles, não precisará tocar nesse subconjunto novamente, basta adicioná-lo. Isso converte a recursão inerente ao quicksort em uma recursão de cauda e, portanto, pode ser reescrita como um loop.hh1h1
Meu Haskell está um pouco enferrujado, mas isso deve fazer o que descrevi acima e parece funcionar. Espero que possa ser entendido até certo ponto, estou feliz em fornecer mais explicações.
-- 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 []
A idéia é coletar o granted
que você sabe que definitivamente participará do resultado e não o classificará mais. Se, greater
juntamente com x
ataques, tivermos sorte, caso contrário, precisamos tentar com um subconjunto menor. (O pivô x
é simplesmente o que aconteceu para ser o primeiro item da sub-lista que é actualmente considerado.) Note-se que a vantagem significativa contra a tomada de maiores elementos, um por um é que fazemos isso em blocos de tamanho médio e não precisa classificá-los ainda mais.r e m a i n i n g/ 2
Exemplo:
Vamos levar o seu set [1,3,4,1,3,6]
.
x = 1
, granted = []
, greater = [3,4,1,3,6]
. Ai, chegamos a um caso patológico quando o pivô é muito pequeno (na verdade, tão pequeno que smaller
está vazio) logo no primeiro passo. Felizmente, nosso algo está pronto para isso. Ele descarta x
e tenta novamente greater
sozinho.
x = 3
, granted = []
, greater = [4,3,6]
. Juntos, eles formam uma matriz de comprimento 4, mas temos apenas o limite inferior de 3 por isso é demais. Repita o procedimento greater
sozinho.
x = 4
, granted = []
, greater = [6]
. Isso fornece uma matriz de 2 elementos ≥ 4 cada, parece que poderíamos usar para mais alguns deles. Mantenha isso e repita smaller = [3]
.
x = 3
, granted = [4,6]
, greater = []
. Juntos, isso fornece uma matriz de 3 elementos ≥ 3 cada, para que tenhamos nossa solução [3,4,6]
e possamos retornar. (Observe que a permutação pode variar dependendo da ordem da entrada, mas sempre conterá os termos mais altos possíveis, nunca [3,3,6]
ou [3,3,4]
para o seu exemplo.)
(Observe que a recursão realmente caiu em um ciclo.) A complexidade é um pouco melhor que a classificação rápida, devido às muitas comparações salvas:
n - 1
O ( logn )O ( n )
nO ( n2)
Existem algumas comparações desnecessárias no código acima, como calcular smaller
se precisamos ou não, elas podem ser facilmente removidas. (Eu acho que a avaliação preguiçosa vai cuidar disso.)