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 de T
's.
Da Wikipedia :
Formalmente, A(1), A(2), ..., A(n)
seja uma sequência de n
números.
Se i < j
e A(i) > A(j)
, então o par (i,j)
é chamado de inversão de A
.
O número de inversão de uma sequência é uma medida comum de sua ordenação.
Formalmente, o número de inversão é definido como o número de inversões, ou seja,
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ão 4
.
Se você deseja um valor entre 0
e 1
, pode dividir o número de inversão por N 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 as N choose 2
inversões. Isso é O(N^2)
inversões corrigidas nas O(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 com O(N log N)
complexidade, é apenas complicado.
Relacionado: calculando o número de "inversões" em uma permutação
Abordagem 2 (Estocástica)
- Amostra aleatória de pares
(i,j)
, ondei != j
- Para cada par, determine se
list[min(i,j)] < list[max(i,j)]
(0 ou 1)
- Calcule a média dessas comparações e depois normalize por
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) e 1
(classificado como crescente), você pode simplesmente mapear o valor acima ( z
), que está entre 0
(classificado como crescente) e 1
(classificado como decrescente), para esse intervalo usando esta fórmula :
z' = -2 * z + 1