Algoritmo de detección del ciclo de Floyd | Determinar el punto de inicio del ciclo

32

Estoy buscando ayuda para comprender el algoritmo de detección de ciclo de Floyd. He revisado la explicación en wikipedia ( http://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare )

Puedo ver cómo el algoritmo detecta el ciclo en el tiempo O (n). Sin embargo, no puedo visualizar el hecho de que una vez que los punteros de la tortuga y la liebre se encuentran por primera vez, el inicio del ciclo se puede determinar moviendo el puntero de la tortuga hacia atrás para comenzar y luego moviendo la tortuga y la liebre un paso a la vez. El punto donde se encuentran por primera vez es el comienzo del ciclo.

¿Alguien puede ayudar proporcionando una explicación, con suerte diferente a la de wikipedia, ya que no puedo entenderla / visualizarla?

Anurag Kapur
fuente
3
Encontré la respuesta en stackoverflow. Gracias si alguien estaba investigando esto por mí. Y para aquellos que como yo quería una explicación, consulte: stackoverflow.com/questions/3952805/… ¡ La respuesta elegida a la pregunta lo explica!
Anurag Kapur
Hola @ Anurag. Solo para su información, he hecho una publicación de blog sobre el algoritmo "Tortuga y la liebre" aquí
Kyle
¿Sabes por qué la fastvariable, o la "liebre" necesita moverse al doble de velocidad que la tortuga, en lugar de solo una adelante?
devdropper87

Respuestas:

47

Puede consultar "Detectar el inicio de un bucle en una lista individualmente vinculada" , aquí hay un extracto:

ingrese la descripción de la imagen aquí

Distancia recorrida slowPointerantes de la reunión =X+y

Distancia recorrida fastPointerantes de la reunión =(X+y+z)+y = x + 2y + z

Ya que fastPointerviaja con el doble de velocidad slowPointer, y el tiempo es constante para ambos cuando llegan al punto de encuentro. Entonces, usando una relación simple de velocidad, tiempo y distancia ( slowPointerrecorrió la mitad de la distancia):

2dist(slowPointer)=dist(fastPointer)2(X+y)=X+2y+z2X+2y=X+2y+zX=z

Por lo tanto, moviéndose slowPointeral inicio de la lista vinculada y haciendo ambos slowPointery fastPointerpara mover un nodo a la vez, ambos tienen la misma distancia que cubrir .

Llegarán al punto donde comienza el ciclo en la lista vinculada.

Viejo monje
fuente
2
Aquí ha asumido que se encontrarán después de una rotación. Puede haber casos (donde el ciclo es pequeño) donde podrían encontrarse después de cierto no. de rotaciones.
Navjot Waraich
1
@JotWaraich la imagen no es representativa de todos los casos; sin embargo, la lógica aún se mantiene
denis631
3
esta es la respuesta más directa sobre este algoritmo en toda Internet
Marshall X
7

También he visto la respuesta aceptada como prueba en otro lugar. Sin embargo, si bien es fácil de asimilar, es incorrecto. Lo que prueba es

X=z (lo cual obviamente es incorrecto, y el diagrama solo lo hace verosímil debido a la forma en que está esbozado).

Lo que realmente quiere probar es (usando las mismas variables que se describen en el diagrama en la respuesta aceptada arriba):

z=X metroore (y+z)

(y+z)L

entonces, lo que queremos probar es:

z=X metroore L

O que z es congruente con x (módulo L)

La siguiente prueba tiene más sentido para mí:

METRO=X+y

2(X+y)=METRO+kLkX+yL

X+y=kL

X=kL-y

XLyMETROX+y

l8 de nuevo
fuente