Eu tenho um problema algorítmico.
Dada uma matriz (ou um conjunto)
Por exemplo:
- Se = [1, 3, 4, 1, 3, 6], então S pode ser [3, 3, 6] ou [3, 4, 6] ou [4, 3, 6].
- Em = [7, 5, 1, 1, 7, 4], então é [7, 5, 7, 4].
Eu tentei essa função recursiva.
function(T):
if minimum(T) >= length(T):
return T
else:
return function(T\minimum(T))
Existe algum algoritmo não recursivo. (Eu não verifiquei meu algoritmo recursivo, portanto, ele pode ter alguma falha.)
algorithms
optimization
sets
drzbir
fonte
fonte
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 ).h h h
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.h h1 h1
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.
A idéia é coletar or e m a i n i n g/ 2
granted
que você sabe que definitivamente participará do resultado e não o classificará mais. Se,greater
juntamente comx
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.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 quesmaller
está vazio) logo no primeiro passo. Felizmente, nosso algo está pronto para isso. Ele descartax
e tenta novamentegreater
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 procedimentogreater
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 repitasmaller = [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:
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.)fonte
Não há nada de errado com seu algoritmo e, é claro, a maioria dos algoritmos recursivos pode ser convertida em loops, aqui uma versão em loop do seu código recursivo:
fonte
Qualquer algoritmo recursivo pode ser reescrito para usar a iteração. Afinal, uma máquina de Turing não sabe nada sobre recursão, mas pode implementar qualquer algoritmo. Em princípio, você pode reescrever sua função recursiva escrevendo seu próprio código de manipulação de pilha para lembrar os valores dos parâmetros da função e quaisquer variáveis locais que ela possa ter. Nesse caso específico, sua função é recursiva de cauda (uma vez que uma chamada recursiva retorna, o que a chamou imediatamente também retorna), assim você nem precisa manter a pilha.
fonte
Use um min-heap para fazer um heapsort parcial, pois você não precisa que toda a matriz seja classificada.
Continue aparecendo os elementos avidamente até exceder o limite especificado.
fonte