Puoi semplicemente contare il numero di inversioni nell'elenco.
Inversione
Un'inversione in una sequenza di elementi di tipo T
è una coppia di elementi di sequenza che appaiono fuori ordine secondo alcuni ordinamenti <
sull'insieme di T
's.
Da Wikipedia :
Formalmente, A(1), A(2), ..., A(n)
sia una sequenza di n
numeri.
Se i < j
e A(i) > A(j)
, la coppia (i,j)
viene chiamata inversione di A
.
Il numero di inversione di una sequenza è una misura comune della sua ordinamento.
Formalmente, il numero di inversione è definito come il numero di inversioni, ovvero
Per rendere più chiare queste definizioni, considerare la sequenza di esempio 9, 5, 7, 6
. Questa sequenza ha le inversioni (0,1), (0,2), (0,3), (2,3)
e il numero di inversione 4
.
Se si desidera un valore tra 0
e 1
, è possibile dividere il numero di inversione per N choose 2
.
Per creare effettivamente un algoritmo per calcolare questo punteggio per quanto è ordinato un elenco, hai due approcci:
Approccio 1 (deterministico)
Modifica il tuo algoritmo di ordinamento preferito per tenere traccia di quante inversioni corregge durante l'esecuzione. Anche se questo non è banale e ha implementazioni variabili a seconda dell'algoritmo di ordinamento che scegli, finirai con un algoritmo che non è più costoso (in termini di complessità) rispetto all'algoritmo di ordinamento che hai iniziato.
Se segui questa strada, tieni presente che non è semplice come contare gli "swap". Mergesort, ad esempio, è il caso peggiore O(N log N)
, ma se viene eseguito in un elenco ordinato in ordine decrescente, correggerà tutte le N choose 2
inversioni. Sono O(N^2)
inversioni corrette nelle O(N log N)
operazioni. Quindi alcune operazioni devono inevitabilmente correggere più di una inversione alla volta. Devi stare attento con la tua implementazione. Nota: puoi farlo con O(N log N)
complessità, è solo complicato.
Correlato: calcolo del numero di "inversioni" in una permutazione
Approccio 2 (stocastico)
- Campionare casualmente coppie
(i,j)
, dovei != j
- Per ogni coppia, determinare se
list[min(i,j)] < list[max(i,j)]
(0 o 1)
- Calcola la media di questi confronti e poi normalizza per
N choose 2
Personalmente seguirei l'approccio stocastico a meno che tu non abbia un requisito di precisione, se non altro perché è così facile da implementare.
Se quello che vuoi veramente è un valore ( z'
) tra -1
(in ordine decrescente) a 1
(in ordine crescente), puoi semplicemente mappare il valore sopra ( z
), che è tra 0
(in ordine crescente) e 1
(in ordine decrescente), a questo intervallo usando questa formula :
z' = -2 * z + 1