Algorithme de détection de cycle de Floyd | Déterminer le point de départ du cycle

32

Je cherche de l'aide pour comprendre l'algorithme de détection de cycle de Floyd. J'ai parcouru l'explication sur wikipedia ( http://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare )

Je peux voir comment l'algorithme détecte le cycle en temps O (n). Cependant, je ne peux pas visualiser le fait qu'une fois que les pointeurs de tortue et de lièvre se rencontrent pour la première fois, le début du cycle peut être déterminé en déplaçant le pointeur de la tortue pour commencer, puis en déplaçant la tortue et le lièvre une étape à la fois. Le point où ils se rencontrent pour la première fois est le début du cycle.

Quelqu'un peut-il m'aider en fournissant une explication, si tout va bien différente de celle sur wikipedia, car je ne peux pas la comprendre / la visualiser?

Anurag Kapur
la source
3
J'ai trouvé la réponse sur stackoverflow. Merci si quelqu'un cherchait ça pour moi. Et pour ceux qui comme moi voulaient une explication, veuillez vous référer à: stackoverflow.com/questions/3952805/… La réponse choisie à la question, l'explique!
Anurag Kapur
Salut @Anurag. Juste pour votre information, j'ai fait un article de blog sur l'algorithme "Tortue et lièvre" ici
Kyle
Savez-vous pourquoi la fastvariable, ou le "lièvre" doit se déplacer à deux fois la vitesse de la tortue, plutôt qu'une seule à l'avance?
devdropper87
Joliment expliqué avec le programme: javabypatel.blogspot.in/2015/12/detect-loop-in-linked-list.html
Jayesh

Réponses:

47

Vous pouvez vous référer à "Détection du début d'une boucle dans une liste liée individuellement" , voici un extrait:

entrez la description de l'image ici

Distance parcourue slowPointeravant la rencontre =x+y

fastPointer =(x+y+z)+y

Depuis fastPointervoyage avec le double de la vitesse slowPointeret le temps est constant pour les deux lorsque le point de rencontre atteint. Donc, en utilisant une relation simple de vitesse, de temps et de distance ( slowPointerparcouru la moitié de la distance):

2dist(slowPointer)=dist(fastPointer)2(x+y)=x+2y+z2x+2y=x+2y+zx=z

Par conséquent, en se déplaçant slowPointerau début de la liste chaînée, en faisant les deux slowPointeret fastPointeren déplaçant un nœud à la fois, ils ont tous deux la même distance à parcourir .

Ils atteindront le point où la boucle commence dans la liste chaînée.

Vieux moine
la source
2
Ici, vous avez supposé qu'ils se rencontreront après une rotation. Il peut y avoir des cas (où le cycle est petit) où ils pourraient se rencontrer après un certain non. de rotations.
Navjot Waraich
1
@JotWaraich l'image n'est pas représentative de tous les cas; la logique tient cependant toujours
denis631
3
c'est la réponse la plus simple à propos de cet algorithme dans tout Internet
Marshall X
7

J'ai vu la réponse acceptée comme preuve ailleurs aussi. Cependant, bien qu'il soit facile à grogner, il est incorrect. Ce que cela prouve, c'est

x=z

Ce que vous voulez vraiment prouver, c'est (en utilisant les mêmes variables que celles décrites dans le diagramme dans la réponse acceptée ci-dessus):

z=x mod (y+z)

(y+z)L

donc, ce que nous voulons prouver, c'est:

z=x mod L

Ou que z est congru à x (modulo L)

La preuve suivante a plus de sens pour moi:

M=x+y

2(x+y)=M+kLkx+yL

x+y=kL

x=kLy

xLyMx+y

l8Again
la source