Możesz po prostu policzyć liczbę inwersji na liście.
Odwrócenie
Odwrócenie w ciągu elementów typu T
to para elementów sekwencji, które pojawiają się nie w porządku według pewnego uporządkowania <
na zbiorze elementów T
.
Z Wikipedii :
Formalnie niech A(1), A(2), ..., A(n)
będzie ciągiem n
liczb.
Jeśli i < j
i A(i) > A(j)
, wtedy para (i,j)
nazywany jest odwrócenie się A
.
Liczba inwersji sekwencji jest jedną z powszechnych miar sortowania.
Formalnie liczba inwersji jest definiowana jako liczba inwersji, to znaczy
Aby wyjaśnić te definicje, rozważ przykładową sekwencję 9, 5, 7, 6
. Ta sekwencja ma inwersje (0,1), (0,2), (0,3), (2,3)
i numer inwersji 4
.
Jeśli chcesz uzyskać wartość między 0
a 1
, możesz podzielić liczbę inwersji przez N choose 2
.
Aby faktycznie utworzyć algorytm obliczający ten wynik dla posortowania listy, masz dwa podejścia:
Podejście 1 (deterministyczne)
Zmodyfikuj swój ulubiony algorytm sortowania, aby śledzić, ile inwersji koryguje podczas działania. Chociaż jest to nietrywialne i ma różne implementacje w zależności od wybranego algorytmu sortowania, otrzymasz algorytm, który nie jest droższy (pod względem złożoności) niż algorytm sortowania, od którego zacząłeś.
Jeśli wybierzesz tę trasę, pamiętaj, że nie jest to tak proste, jak liczenie „zamiany”. Na przykład scalanie jest najgorszym przypadkiem O(N log N)
, ale jeśli zostanie uruchomione na liście posortowanej w porządku malejącym, poprawi wszystkie N choose 2
inwersje. To jest O(N^2)
odwrócenie poprawione w O(N log N)
operacjach. Dlatego niektóre operacje muszą nieuchronnie korygować więcej niż jedną inwersję naraz. Musisz uważać na swoją implementację. Uwaga: możesz to zrobić ze O(N log N)
złożonością, to po prostu trudne.
Powiązane: obliczanie liczby „inwersji” w permutacji
Podejście 2 (stochastyczne)
- Losowe pary próbek
(i,j)
, gdziei != j
- Dla każdej pary określ, czy
list[min(i,j)] < list[max(i,j)]
(0 czy 1)
- Oblicz średnią z tych porównań, a następnie znormalizuj według
N choose 2
Osobiście wybrałbym podejście stochastyczne, chyba że masz wymóg dokładności - choćby dlatego, że jest tak łatwy do wdrożenia.
Jeśli naprawdę potrzebujesz wartości ( z'
) między -1
(posortowane malejąco) do 1
(posortowane rosnąco), możesz po prostu zmapować wartość powyżej ( z
), która znajduje się pomiędzy 0
(posortowano rosnąco) i 1
(posortowano malejąco), na ten zakres przy użyciu tej formuły :
z' = -2 * z + 1