Vous pouvez simplement compter le nombre d'inversions dans la liste.
Inversion
Une inversion dans une séquence d'éléments de type T
est une paire d'éléments de séquence qui apparaissent dans le désordre selon un ordre <
sur l'ensemble des T
's.
De Wikipedia :
Formellement, laissez A(1), A(2), ..., A(n)
être une séquence de n
nombres.
Si i < j
et A(i) > A(j)
, alors la paire (i,j)
est appelée une inversion de A
.
Le numéro d'inversion d'une séquence est une mesure courante de son tri.
Formellement, le nombre d'inversion est défini comme étant le nombre d'inversions, c'est-à-dire
Pour rendre ces définitions plus claires, considérez l'exemple de séquence 9, 5, 7, 6
. Cette séquence a les inversions (0,1), (0,2), (0,3), (2,3)
et le numéro d'inversion 4
.
Si vous voulez une valeur entre 0
et 1
, vous pouvez diviser le nombre d'inversion par N choose 2
.
Pour créer réellement un algorithme pour calculer ce score en fonction du tri d'une liste, vous avez deux approches:
Approche 1 (déterministe)
Modifiez votre algorithme de tri préféré pour garder une trace du nombre d'inversions qu'il corrige pendant son exécution. Bien que cela ne soit pas trivial et ait des implémentations variables en fonction de l'algorithme de tri que vous choisissez, vous vous retrouverez avec un algorithme qui n'est pas plus cher (en termes de complexité) que l'algorithme de tri avec lequel vous avez commencé.
Si vous empruntez cette voie, sachez que ce n'est pas aussi simple que de compter les «swaps». Mergesort, par exemple, est le pire des cas O(N log N)
, mais s'il est exécuté sur une liste triée par ordre décroissant, il corrigera toutes les N choose 2
inversions. Ce sont des O(N^2)
inversions corrigées dans les O(N log N)
opérations. Ainsi, certaines opérations doivent inévitablement corriger plus d'une inversion à la fois. Vous devez être prudent avec votre mise en œuvre. Remarque: vous pouvez le faire avec O(N log N)
complexité, c'est juste délicat.
En relation: calcul du nombre «d'inversions» dans une permutation
Approche 2 (stochastique)
- Échantillonner au hasard des paires
(i,j)
, oùi != j
- Pour chaque paire, déterminez si
list[min(i,j)] < list[max(i,j)]
(0 ou 1)
- Calculer la moyenne de ces comparaisons puis normaliser par
N choose 2
Personnellement, j'opterais pour l'approche stochastique à moins que vous n'ayez une exigence d'exactitude - ne serait-ce que parce qu'elle est si facile à mettre en œuvre.
Si vous voulez vraiment une valeur ( z'
) entre -1
(triée par ordre décroissant) et 1
(triée par ordre croissant), vous pouvez simplement mapper la valeur ci-dessus ( z
), qui se situe entre 0
(triée par ordre croissant) et 1
(triée par ordre décroissant), à cette plage en utilisant cette formule :
z' = -2 * z + 1