Vorrei provare a chiarire l'algoritmo di rilevazione del ciclo fornito su http://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare con parole mie.
Come funziona
Prendiamo una tartaruga e una lepre (nome dei puntatori) che indicano l'inizio dell'elenco con un ciclo, come nel diagramma sopra.
Ipotizziamo che se spostiamo la tartaruga di 1 passo alla volta e lepre 2 passi alla volta, alla fine si incontreranno. Mostriamo che prima di tutto questa ipotesi è vera.
La figura illustra un elenco con un ciclo. Il ciclo ha una lunghezza di n
e siamo inizialmente a m
pochi passi dal ciclo. Diciamo anche che il punto d'incontro è a k
pochi passi dall'inizio del ciclo e tartaruga e lepre si incontrano quando la tartaruga ha compiuto i
passi totali. (La lepre avrebbe già compiuto 2i
passi totali da allora.).
Devono essere valide le seguenti 2 condizioni:
1) i = m + p * n + k
2) 2i = m + q * n + k
Il primo dice che la tartaruga muove i i
passi e in questi i
passi arriva prima al ciclo. Quindi passa attraverso i p
tempi di ciclo per un numero positivo p
. Alla fine supera k
più nodi fino a quando non incontra la lepre.
Un simile è vero per la lepre. Muove i 2i
passi e in questi 2i
passi arriva prima al ciclo. Quindi passa attraverso i q
tempi di ciclo per un numero positivo q
. Alla fine supera k
più nodi fino a quando incontra la tartaruga.
Mentre la lepre viaggia con il doppio della velocità della tartaruga, e il tempo è costante per entrambi quando raggiungono il punto di incontro.
Quindi, usando la semplice relazione velocità, tempo e distanza,
2 ( m + p * n + k ) = m + q * n + k
=> 2m + 2pn + 2k = m + nq + k
=> m + k = ( q - 2p ) n
Tra m, n, k, p, q, i primi due sono proprietà dell'elenco indicato. Se possiamo mostrare che esiste almeno un insieme di valori per k, q, p che rende vera questa equazione, mostriamo che l'ipotesi è corretta.
Una di queste soluzioni è la seguente:
p = 0
q = m
k = m n - m
Possiamo verificare che questi valori funzionino come segue:
m + k = ( q - 2p ) n
=> m + mn - m = ( m - 2*0) n
=> mn = mn.
Per questo set, i
è
i = m + p n + k
=> m + 0 * n + mn - m = mn.
Naturalmente, dovresti vedere che questo non è necessariamente il più piccolo possibile. In altre parole, la tartaruga e la lepre potrebbero essersi già incontrate molte volte. Tuttavia, poiché dimostriamo che si incontrano ad un certo punto almeno una volta, possiamo dire che l'ipotesi è corretta. Quindi dovrebbero incontrarsi se spostiamo uno di loro di 1 passo e l'altro di 2 passi alla volta.
Ora possiamo andare alla seconda parte dell'algoritmo che è come trovare l'inizio del ciclo.
Inizio del ciclo
Una volta che la tartaruga e la lepre si incontrano, rimettiamo la tartaruga all'inizio dell'elenco e manteniamo la lepre dove si sono incontrati (che è k passi dall'inizio del ciclo).
L'ipotesi è che se li lasciamo muovere alla stessa velocità (1 passo per entrambi), la prima volta che si incontreranno di nuovo sarà l'inizio del ciclo.
Dimostriamo questa ipotesi.
Supponiamo per prima cosa che un oracolo ci dica cos'è m.
Quindi, se li lasciamo muovere passi di m + k, la tartaruga dovrebbe arrivare nel punto in cui si sono incontrati originariamente (k passi di distanza dall'inizio del ciclo - vedi in figura).
In precedenza lo avevamo dimostrato m + k = (q - 2p) n
.
Poiché m + k passi è un multiplo della lunghezza del ciclo n, la lepre, nel frattempo, attraverserebbe il ciclo (q-2p) volte e ritornerebbe allo stesso punto (k passi all'inizio del ciclo).
Ora, invece di lasciarli muovere m + k passi, se li lasciamo muovere solo m passi, la tartaruga arriverebbe all'inizio del ciclo. La lepre sarebbe k passi prima del completamento delle rotazioni (q-2p). Da quando ha iniziato k passi all'inizio del ciclo, la lepre dovrebbe arrivare all'inizio del ciclo.
Di conseguenza, questo spiega che avrebbero dovuto incontrarsi all'inizio del ciclo dopo un certo numero di passaggi per la prima volta (la prima volta perché la tartaruga era appena arrivata al ciclo dopo m passi e non poteva mai vedere la lepre che era già in il ciclo).
Ora sappiamo che il numero di passaggi necessari per spostarli fino a quando si incontrano risulta essere la distanza tra l'inizio dell'elenco e l'inizio del ciclo, m. Naturalmente, l'algoritmo non ha bisogno di sapere cos'è m. Sposterà sia la tartaruga che la lepre un passo alla volta fino a quando non si incontreranno. Il punto di incontro deve essere l'inizio del ciclo e il numero di passi deve essere la distanza (m) all'inizio del ciclo. Supponendo che conosciamo la lunghezza dell'elenco, possiamo anche calcolare la lunghezza del ciclo di sottrazione di m dalla lunghezza dell'elenco.