Existe uma maneira de medir a classificação de uma lista?
Quero dizer, não se trata de saber se uma lista está classificada ou não (booleana), mas algo como uma proporção de "gentileza", algo como o coeficiente de correlação nas estatísticas.
Por exemplo,
Se os itens de uma lista estiverem em ordem crescente, sua taxa será 1,0
Se a lista for classificada como decrescente, sua taxa será -1,0
Se a lista estiver quase classificada em ordem crescente, sua taxa seria 0,9 ou algum valor próximo a 1.
Se a lista não for classificada (aleatoriamente), sua taxa será próxima de 0
Estou escrevendo uma pequena biblioteca em Scala para praticar. Acho que uma taxa de classificação seria útil, mas não encontro informações sobre algo assim. Talvez eu não conheça termos adequados para o conceito.
Respostas:
Você pode simplesmente contar o número de inversões na lista.
Inversão
Uma inversão em uma sequência de elementos do tipo
T
é um par de elementos de sequência que aparecem fora de ordem, de acordo com algumas ordens<
no conjunto deT
's.Da Wikipedia :
Para tornar essas definições mais claras, considere a sequência de exemplo
9, 5, 7, 6
. Esta sequência possui as inversões(0,1), (0,2), (0,3), (2,3)
e o número de inversão4
.Se você deseja um valor entre
0
e1
, pode dividir o número de inversão porN choose 2
.Para realmente criar um algoritmo para calcular essa pontuação pela classificação de uma lista, você tem duas abordagens:
Abordagem 1 (determinística)
Modifique seu algoritmo de classificação favorito para acompanhar quantas inversões está corrigindo à medida que é executado. Embora isso não seja trivial e tenha implementações variadas, dependendo do algoritmo de classificação escolhido, você terminará com um algoritmo que não é mais caro (em termos de complexidade) do que o algoritmo de classificação com o qual você iniciou.
Se você seguir esse caminho, saiba que não é tão simples quanto contar "trocas". O mergesort, por exemplo, é o pior caso
O(N log N)
, mas se for executado em uma lista classificada em ordem decrescente, ele corrigirá todas asN choose 2
inversões. Isso éO(N^2)
inversões corrigidas nasO(N log N)
operações. Portanto, algumas operações devem inevitavelmente corrigir mais de uma inversão de cada vez. Você precisa ter cuidado com sua implementação. Nota: você pode fazer isso comO(N log N)
complexidade, é apenas complicado.Relacionado: calculando o número de "inversões" em uma permutação
Abordagem 2 (Estocástica)
(i,j)
, ondei != j
list[min(i,j)] < list[max(i,j)]
(0 ou 1)N choose 2
Eu pessoalmente adotaria a abordagem estocástica, a menos que você exija uma exigência de exatidão - mesmo que seja tão fácil de implementar.
Se o que você realmente deseja é um valor (
z'
) entre-1
(classificado como decrescente) e1
(classificado como crescente), você pode simplesmente mapear o valor acima (z
), que está entre0
(classificado como crescente) e1
(classificado como decrescente), para esse intervalo usando esta fórmula :fonte
A medida tradicional de como uma lista é classificada (ou outra estrutura seqüencial) é o número de inversões.
O número de inversões é o número de pares (a, b) st índice de a <b AND b
<<
a. Para esses fins,<<
representa qualquer relação de pedido que você escolher para seu tipo específico.Uma lista totalmente classificada não possui inversões e uma lista completamente revertida possui o número máximo de inversões.
fonte
5 4 3 2 1
é totalmente classificado, uma vez que a ordem não está especificada, mas estou sendo pedante :-) #<
.n choose 2
.Você pode usar correlação real.
Suponha que, para cada item da lista classificada, você atribua uma classificação inteira começando do zero. Observe que um gráfico do índice de posição dos elementos versus classificação se parecerá com pontos em uma linha reta (correlação de 1,0 entre a posição e a classificação).
Você pode calcular uma correlação com esses dados. Para uma classificação inversa, você receberá -1 e assim por diante.
fonte
Houve ótimas respostas, e eu gostaria de acrescentar um aspecto matemático para completar:
Você pode medir a classificação de uma lista, medindo o quanto ela está correlacionada a uma lista classificada. Para fazer isso, você pode usar a correlação de classificação (a mais conhecida é a de Spearman ), que é exatamente igual à correlação usual, mas usa a classificação de elementos em uma lista em vez dos valores analógicos de seus itens.
Existem muitas extensões, como um coeficiente de correlação (+1 para classificação exata, -1 para inversão exata)
Isso permite que você tenha propriedades estatísticas para essa medida, como o teorema do limite central permutacional, que permite conhecer a distribuição dessa medida para listas aleatórias.
fonte
Além da contagem de inversões, para listas numéricas, é possível imaginar a distância quadrada média do estado classificado:
fonte
Não tenho certeza do método "melhor", mas um método simples seria comparar todos os elementos com o que se segue, incrementando um contador se element2> elemento 1 (ou o que você deseja testar) e depois dividir pelo número total de elementos. Deve lhe dar uma porcentagem.
fonte
Eu contaria comparações e dividiria para o número total de comparações. Aqui está um exemplo simples do Python .
fonte
Que tal algo como isso?
fonte
Se você pegar sua lista, calcular as classificações dos valores nessa lista e chamar a lista de classificações
Y
e outra lista,X
que contém os números inteiros de1
atélength(Y)
, poderá obter exatamente a medida de classificação que está procurando, calculando o coeficiente de correlação ,r
entre as duas listas.Para uma lista totalmente classificada ,,
r = 1.0
para uma lista classificada inversar=-1.0
, e ar
varia entre esses limites para graus variados de classificação.Um possível problema com essa abordagem, dependendo do aplicativo, é que calcular a classificação de cada item na lista é equivalente a classificá-lo, portanto, é uma operação O (n log n).
fonte