Permítanme intentar aclarar el algoritmo de detección de ciclo que se proporciona en http://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare en mis propias palabras.
Cómo funciona
Tengamos una tortuga y una liebre (nombre de los punteros) que señalen el comienzo de la lista con un ciclo, como en el diagrama anterior.
Supongamos que si movemos la tortuga 1 paso a la vez, y tenemos 2 pasos a la vez, eventualmente se encontrarán en un punto. Demostremos que, en primer lugar, esta hipótesis es cierta.
La figura ilustra una lista con un ciclo. El ciclo tiene una duración de n
e inicialmente estamos a unos m
pasos del ciclo. También digamos que el punto de encuentro está a k
pasos del comienzo del ciclo y la tortuga y la liebre se encuentran cuando la tortuga ha dado los i
pasos totales. (Hare habría dado 2i
pasos totales para entonces).
Las siguientes 2 condiciones deben cumplir:
1) i = m + p * n + k
2) 2i = m + q * n + k
El primero dice que la tortuga mueve i
pasos y en estos i
pasos primero llega al ciclo. Luego pasa por los p
tiempos de ciclo para algún número positivo p
. Finalmente, pasa por k
más nodos hasta que se encuentra con la liebre.
Un similar es cierto para la liebre. Mueve los 2i
pasos y en estos 2i
pasos primero llega al ciclo. Luego pasa por los q
tiempos de ciclo para algún número positivo q
. Finalmente, pasa por k
más nodos hasta que se encuentra con la tortuga.
Como la liebre viaja con el doble de velocidad que la tortuga, y el tiempo es constante para ambos cuando llegan al punto de encuentro.
Entonces, usando una relación simple de velocidad, tiempo y distancia,
2 ( m + p * n + k ) = m + q * n + k
=> 2m + 2pn + 2k = m + nq + k
=> m + k = ( q - 2p ) n
Entre m, n, k, p, q, los dos primeros son propiedades de la lista dada. Si podemos demostrar que hay al menos un conjunto de valores para k, q, p que hace que esta ecuación sea verdadera, mostramos que la hipótesis es correcta.
Uno de estos conjuntos de soluciones es el siguiente:
p = 0
q = m
k = m n - m
Podemos verificar que estos valores funcionen de la siguiente manera:
m + k = ( q - 2p ) n
=> m + mn - m = ( m - 2*0) n
=> mn = mn.
Para este conjunto, i
es
i = m + p n + k
=> m + 0 * n + mn - m = mn.
Por supuesto, deberías ver que esto no es necesariamente el más pequeño posible. En otras palabras, la tortuga y la liebre ya podrían haberse encontrado antes muchas veces. Sin embargo, como mostramos que se encuentran en algún momento al menos una vez, podemos decir que la hipótesis es correcta. Por lo tanto, tendrían que reunirse si movimos uno de ellos 1 paso, y el otro 2 pasos a la vez.
Ahora podemos pasar a la segunda parte del algoritmo, que es cómo encontrar el comienzo del ciclo.
Comienzo del ciclo
Una vez que la tortuga y la liebre se encuentran, volvamos a la tortuga al principio de la lista y mantengamos la liebre donde se encontraron (que está a k pasos del comienzo del ciclo).
La hipótesis es que si dejamos que se muevan a la misma velocidad (1 paso para ambos), la primera vez que se vuelvan a encontrar será el comienzo del ciclo.
Probemos esta hipótesis.
Primero supongamos que algún oráculo nos dice qué es m.
Luego, si dejamos que muevan m + k pasos, la tortuga tendría que llegar al punto en que se encontraron originalmente (k pasos lejos del comienzo del ciclo, ver en la figura).
Anteriormente mostramos eso m + k = (q - 2p) n
.
Dado que m + k pasos es un múltiplo de la longitud del ciclo n, la liebre, en el tiempo medio, pasaría por el ciclo (q-2p) veces y volvería al mismo punto (k pasos lejos del comienzo del ciclo).
Ahora, en lugar de dejar que se muevan m + k pasos, si dejamos que se muevan solo m pasos, la tortuga llegaría al comienzo del ciclo. La liebre estaría a k pasos de completar (q-2p) rotaciones. Como comenzó k pasos delante del comienzo del ciclo, las liebres tendrían que llegar al comienzo del ciclo.
Como resultado, esto explica que tendrían que reunirse en el ciclo que comienza después de cierto número de pasos por primera vez (la primera vez porque la tortuga acaba de llegar al ciclo después de m pasos y nunca podría ver liebre que ya estaba en el ciclo).
Ahora sabemos que la cantidad de pasos que necesitamos para moverlos hasta que se encuentren resulta ser la distancia desde el comienzo de la lista hasta el comienzo del ciclo, m. Por supuesto, el algoritmo no necesita saber qué es m. Solo moverá la tortuga y la liebre paso a paso hasta que se encuentren. El punto de encuentro debe ser el inicio del ciclo y el número de pasos debe ser la distancia (m) al comienzo del ciclo. Suponiendo que conocemos la longitud de la lista, también podemos calcular la longitud del ciclo de restar m de la longitud de la lista.