Spróbuję wyjaśnić własnymi słowami algorytm wykrywania cykli, który znajduje się pod adresem http://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare .
Jak to działa
Niech żółw i zając (nazwa wskaźników) wskazują na początek listy cyklem, jak na powyższym schemacie.
Postawmy hipotezę, że jeśli przesuniemy żółwia o 1 krok na raz i zając o 2 kroki na raz, w końcu spotkają się w pewnym momencie. Pokażmy, że przede wszystkim ta hipoteza jest prawdziwa.
Rysunek przedstawia listę z cyklem. Cykl ma długość n
i początkowo m
oddalamy się od niego o kilka kroków. Powiedzmy również, że miejsce spotkania jest k
kilka kroków od początku cyklu, a żółw i zając spotykają się, gdy żółw zrobi i
całkowite kroki. (Hare podjąłby wtedy 2i
totalne kroki).
Muszą być spełnione następujące 2 warunki:
1) i = m + p * n + k
2) 2i = m + q * n + k
Pierwsza mówi, że żółw porusza się po i
krokach iw tych i
krokach najpierw dostaje się do cyklu. Następnie przechodzi przez p
czasy cyklu dla pewnej liczby dodatniej p
. W końcu przechodzi przez k
kolejne węzły, aż napotka zająca.
Podobnie jest z zającem. Porusza się 2i
krokami iw tych 2i
krokach najpierw dostaje się do cyklu. Następnie przechodzi przez q
czasy cyklu dla pewnej liczby dodatniej q
. W końcu przechodzi przez k
więcej węzłów, aż napotka żółwia.
Ponieważ zając podróżuje z podwójną prędkością żółwia, a czas jest stały dla obu, kiedy docierają do miejsca spotkania.
Używając prostej zależności prędkości, czasu i odległości,
2 ( m + p * n + k ) = m + q * n + k
=> 2m + 2pn + 2k = m + nq + k
=> m + k = ( q - 2p ) n
Spośród m, n, k, p, q, pierwsze dwie są właściwościami podanej listy. Jeśli potrafimy wykazać, że istnieje co najmniej jeden zbiór wartości k, q, p, który sprawia, że to równanie jest prawdziwe, to pokażemy, że hipoteza jest poprawna.
Jeden taki zestaw rozwiązań wygląda następująco:
p = 0
q = m
k = m n - m
Możemy sprawdzić, czy te wartości działają w następujący sposób:
m + k = ( q - 2p ) n
=> m + mn - m = ( m - 2*0) n
=> mn = mn.
W tym zestawie i
jest
i = m + p n + k
=> m + 0 * n + mn - m = mn.
Oczywiście powinieneś zobaczyć, że niekoniecznie jest to najmniejsze możliwe. Innymi słowy, żółw i zając mogły się już spotkać wiele razy. Ponieważ jednak pokazujemy, że spotykają się one przynajmniej raz, możemy powiedzieć, że hipoteza jest poprawna. Więc musieliby się spotkać, gdybyśmy przesunęli jeden z nich o 1 stopień, a drugi o 2 stopnie naraz.
Teraz możemy przejść do drugiej części algorytmu, czyli znaleźć początek cyklu.
Początek cyklu
Gdy żółw i zając spotkają się, umieśćmy żółwia z powrotem na początku listy i trzymajmy zająca w miejscu, w którym się spotkali (czyli o k kroków od początku cyklu).
Hipoteza jest taka, że jeśli pozwolimy im poruszać się z tą samą prędkością (1 krok dla obu), pierwszy raz spotkają się ponownie, będzie to początek cyklu.
Udowodnijmy tę hipotezę.
Załóżmy najpierw, że jakaś wyrocznia mówi nam, czym jest m.
Następnie, jeśli pozwolimy im poruszać się m + k kroków, żółw musiałby dotrzeć do punktu, w którym pierwotnie się spotkali (k kroków od początku cyklu - patrz rysunek).
Wcześniej to pokazaliśmy m + k = (q - 2p) n
.
Ponieważ m + k kroków jest wielokrotnością długości cyklu n, zając w międzyczasie przeszedłby cykl (q-2p) razy i wróciłby do tego samego punktu (k kroków od początku cyklu).
Teraz, zamiast pozwolić im poruszać się m + k kroków, jeśli pozwolimy im poruszać się tylko m kroków, żółw przybyłby na początek cyklu. Zającowi brakłoby k kroków do wykonania obrotów (q-2p). Ponieważ zaczynał k kroków przed początkiem cyklu, zając musiałby dojść do początku cyklu.
W rezultacie wyjaśnia to, że musieliby spotkać się na początku cyklu po pewnej liczbie kroków po raz pierwszy (za pierwszym razem, ponieważ żółw właśnie przybył do cyklu po m krokach i nigdy nie widział zająca, który był już w cykl).
Teraz wiemy, że liczba kroków, które musimy przesunąć, aż się spotkają, okazuje się być odległością od początku listy do początku cyklu, m. Oczywiście algorytm nie musi wiedzieć, czym jest m. Po prostu poruszy zarówno żółwia, jak i zająca, krok po kroku, aż się spotkają. Punktem spotkania musi być początek cyklu, a liczba kroków musi być odległością (m) do początku cyklu. Zakładając, że znamy długość listy, możemy również obliczyć długość cyklu odejmowania m od długości listy.