web-dev-qa-db-fra.com

Expliquez comment trouver un nœud de début de cycle dans la liste chaînée de cycles?

Je crois comprendre que la réunion de Tortue et Hare conclut à l’existence d’une boucle, mais comment déplacer une tortue au début de la liste chaînée tout en gardant le lièvre au lieu de la réunion, suivi du déplacement d’une étape à la fois, les fait se rencontrer au début du cycle?

142

Ceci est algorithme de Floyd pour la détection de cycle . Vous vous interrogez sur la deuxième phase de l'algorithme - une fois que vous avez trouvé un nœud faisant partie d'un cycle, comment trouve-t-on le début du cycle?

Dans la première partie de l'algorithme de Floyd, le lièvre se déplace de deux pas pour chaque pas de la tortue. Si la tortue et le lièvre se rencontrent, il y a un cycle et le point de rencontre fait partie du cycle, mais pas nécessairement le premier nœud du cycle.

Lorsque la tortue et le lièvre se sont rencontrés, nous avons trouvé le plus petit i (le nombre de pas effectués par la tortue) tel que Xje = X2i. Laisser mu représenter le nombre de pas à obtenir de X au début du cycle, et laissez lambda représenter la durée du cycle. Alors i = mu + a lambda, et 2i = mu + b lambda, où a et b sont des nombres entiers indiquant le nombre de fois que la tortue et le lièvre ont parcouru le cycle. En soustrayant la première équation de la seconde, on obtient i = (b-a) * lambda, donc i est un multiple entier de lambda. Par conséquent, Xi + mu = Xmu. Xje représente le point de rencontre de la tortue et du lièvre. Si vous ramenez la tortue sur le nœud de départ X, et laissez la tortue et le lièvre continuer à la même vitesse, après plusieurs étapes la tortue aura atteint Xmuet le lièvre aura atteint Xi + mu = XmuLe deuxième point de rendez-vous correspond donc au début du cycle.

71
Jim Lewis

Permettez-moi d'essayer de clarifier l'algorithme de détection de cycle fourni à l'adresse http://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare dans mes propres mots.

drawing

Comment ça marche

Prenons une tortue et un lièvre (nom des pointeurs) pointant vers le début de la liste avec un cycle, comme dans le diagramme ci-dessus.

Faisons l'hypothèse que si nous déplaçons une tortue une étape à la fois et que nous en avons deux à la fois, elles se rencontreront à un moment donné. Montrons tout d'abord que cette hypothèse est vraie.

La figure illustre une liste avec un cycle. Le cycle a une longueur de n et nous sommes initialement m à quelques pas du cycle. Supposons également que le point de rencontre est k à l’écart du début du cycle et que tortue et lièvre se rencontrent lorsque la tortue a pris i pas-à-pas. (Hare aurait pris 2i Pas plus tard.).

Les 2 conditions suivantes doivent être remplies:

1) i = m + p * n + k

2) 2i = m + q * n + k

Le premier indique que la tortue se déplace i étapes et que, dans ces i étapes, elle passe d’abord au cycle. Ensuite, il parcourt le cycle p fois pour un nombre positif p. Enfin, il passe sur k plusieurs nœuds jusqu’à ce qu’il rencontre le lièvre.

Un semblable est vrai pour le lièvre. Il déplace les étapes 2i Et dans ces étapes 2i, Il arrive d'abord au cycle. Ensuite, il parcourt le cycle q fois pour un nombre positif q. Enfin, il passe sur k plus de nœuds jusqu’à ce qu’il rencontre une tortue.

Comme le lièvre se déplace deux fois plus vite que la tortue, le temps est constant pour les deux quand ils atteignent le point de rendez-vous.

Donc, en utilisant une relation simple de vitesse, de temps et de distance,

2 ( m + p * n + k ) = m + q * n + k

=> 2m + 2pn + 2k = m + nq + k 

=>  m + k = ( q - 2p ) n

Parmi m, n, k, p, q, les deux premiers sont des propriétés de la liste donnée. Si nous pouvons montrer qu'il existe au moins un ensemble de valeurs pour k, q, p qui rend cette équation vraie, nous montrons que l'hypothèse est correcte.

Une de ces solutions est la suivante:

p = 0

q = m

k = m n - m

Nous pouvons vérifier que ces valeurs fonctionnent comme suit:

m + k = ( q - 2p ) n  

=> m + mn - m = ( m - 2*0) n

=> mn = mn.

Pour cet ensemble, i est

i = m + p n + k

=> m + 0 * n + mn - m = mn.

Bien sûr, vous devriez voir que ce n’est pas nécessairement le plus petit possible. En d'autres termes, la tortue et le lièvre se sont peut-être déjà rencontrés plusieurs fois auparavant. Cependant, puisque nous montrons qu’ils se rencontrent à un moment donné au moins une fois, nous pouvons dire que l’hypothèse est correcte. Ils devraient donc se rencontrer si nous déplaçons l’une d’elles 1 étape et l’autre 2 étapes à la fois.

Nous pouvons maintenant passer à la deuxième partie de l’algorithme, à savoir comment trouver le début du cycle.

Début du cycle

Une fois que la tortue et le lièvre se sont rencontrés, remettons la tortue au début de la liste et conservons le lièvre là où ils se sont rencontrés (à k pas du début du cycle).

L'hypothèse est que si nous les laissons avancer à la même vitesse (1 pas pour les deux), la première fois qu'ils se reverront, ce sera le début du cycle.

Prouvons cette hypothèse.

Supposons tout d'abord qu'un Oracle nous dit ce que m est.

Ensuite, si nous les laissons bouger m + k pas à pas, la tortue devrait arriver au point où elle s’était rencontrée à l’origine (à un pas de k du début du cycle - voir la figure).

Auparavant, nous avions montré que m + k = (q - 2p) n.

Étant donné que m + k pas est un multiple de la longueur du cycle n, le lièvre parcourrait en même temps les cycles (q-2p) et reviendrait au même point (k pas loin du début du cycle).

Maintenant, au lieu de les laisser bouger m + k marches, si on ne les laisse bouger que m, la tortue arriverait au début du cycle. Le lièvre aurait quelques étapes avant la fin des rotations (q-2p). Comme il a commencé k pas avant le début du cycle, le lièvre devrait arriver au début du cycle.

En conséquence, cela explique qu’ils devraient se retrouver au cycle qui commence après un certain nombre de marches pour la toute première fois (car la tortue vient d’arriver au cycle après m et qu’elle ne pouvait jamais voir le lièvre qui était déjà le cycle).

Nous savons maintenant que le nombre d’étapes dont nous avons besoin pour les déplacer jusqu’à ce qu’elles se rencontrent s’avère être la distance entre le début de la liste et le début du cycle, m. Bien sûr, l'algorithme n'a pas besoin de savoir ce que m est. Il ne fera que déplacer les tortues et les lièvres un à un jusqu'à ce qu'ils se rencontrent. Le point de rendez-vous doit être le début du cycle et le nombre d'étapes doit être la distance (m) jusqu'au début du cycle. En supposant que nous connaissions la longueur de la liste, nous pouvons également calculer la longueur du cycle de soustraction m de la longueur de la liste.

301
CEGRD

Référez cette image:

enter image description here

Distance parcourue par slowPointer avant la réunion = x + y

Distance parcourue par fastPointer avant la réunion = (x + y + z) + y = x + 2y + z

Puisque fastPointer se déplace avec double la vitesse de slowPointer et le temps est constant pour les deux quand le atteindre le point de rencontre.

Donc, en utilisant une relation simple vitesse, temps et distance 2 (x + y) = x + 2y + z => x + 2y + z = 2x + 2y => x = z

Par conséquent, en déplaçant slowPointer en début de liste chaînée, et en faisant en sorte que slowPointer et fastPointer déplacent un nœud à la fois ils ont tous deux la même distance à parcourir .

Ils arriveront au point où la boucle commence dans la liste liée.

114
Old Monk

La réponse simple et sous-votée de Old Monk explique comment trouver le cycle lorsque le coureur rapide ne termine qu'un seul cycle complet. Dans cette réponse, j'explique le cas où un coureur rapide a exécuté la boucle plusieurs fois avant que le coureur lent ne s'engage dans la boucle.


En utilisant la même image: enter image description here

Disons que le coureur rapide a parcouru la boucle m fois avant la lente et rapide rencontre. Cela signifie que:

  • Distance parcourue par slow: x + y
  • Distance parcourue par rapide: x + m (y + z) + y c'est-à-dire supplémentaire y où ils se rencontrent

Étant donné que les courses rapides sont deux fois plus rapides que les ralentis et qu’ils courent depuis le même temps, cela signifie que si nous doublons la distance parcourue par lente, nous courons rapidement. Ainsi,

  • 2 (x + y) = x + m (y + z) + y

Résoudre pour x donne,

x = (m - 1) (y + z) + z

Dans un scénario réel, cela signifierait, x = (m - 1) boucle complète exécute + une distance supplémentaire z .

Par conséquent, si nous plaçons un pointeur au début de la liste et laissons l’autre au point de rendez-vous, leur déplacement à la même vitesse entraînera l’achèvement du pointeur de la boucle entrante m - 1 exécute la boucle puis rencontre l'autre pointeur juste au début de la boucle.

59
displayName

Figure 1

Au moment de la première collision, la tortue a bougé m + k comme indiqué ci-dessus. Le lièvre se déplace deux fois plus vite que la tortue, ce qui signifie un lièvre déplacé 2 (m + k) . À partir de ces faits simples, nous pouvons tirer le graphique suivant.

Figure 1

À ce stade, nous renvoyons la tortue au début et déclarons que le lièvre et la tortue doivent faire un pas à la fois. Par définition, après m , la tortue sera au début du cycle. Où sera le lièvre?

Le lièvre sera également au début du cycle. Cela ressort clairement du second graphique: lorsque la tortue a été renvoyée au début, le lièvre était k entame son dernier cycle . Après m , le lièvre aura terminé un autre cycle et se sera heurté à une tortue.

7
skedastik

C'est très très simple. Vous pouvez penser en termes de vitesse relative. Si le lapin bouge deux nœuds et que la tortue déplace un nœud, par rapport à la tortue, le lapin bouge un nœud (supposons que la tortue soit au repos). Donc, si nous déplaçons un nœud dans la liste chaînée circulaire, nous nous réunirons à nouveau à ce moment-là.

Après avoir trouvé le point connecté dans la liste chaînée circulaire, le problème se réduit maintenant à la recherche du problème du point d’intersection de deux problèmes liés à la liste.

5
murali krish

approche:

Il y a deux pointeurs:

  • Un pointeur lent qui déplace un nœud à la fois.
  • Un pointeur rapide qui déplace deux nœuds à la fois.

Si les deux pointeurs se rencontrent, cela prouve qu'il y a une boucle. Une fois qu’ils se sont rencontrés, l’un des nœuds pointe vers la tête, puis les deux procèdent un par un. Ils se rencontreront au début de la boucle.

Justification: Lorsque deux personnes empruntent une piste circulaire, l'une deux fois plus vite que l'autre, où se rencontrent-elles? Exactement où ils ont commencé.

Maintenant, supposons que le coureur rapide ait une longueur d'avance de k étapes dans un tour n. où vont-ils se rencontrer? Exactement à l'étape n-k. Lorsque le coureur lent a couvert les étapes (n-k), Le coureur rapide aurait couvert les étapes k+2(n-k). ( c'est-à-dire, pas k+2n-2k c'est-à-dire 2n-k pas ). c'est-à-dire (n-k) étapes (le chemin est circulaire et nous ne sommes pas préoccupés par le nombre de rounds après lesquels ils se rencontrent; nous ne sommes intéressés que par la position où ils se rencontrent).

Maintenant, comment le coureur rapide at-il pris l’avance de k pas en premier lieu? Parce qu'il a fallu au coureur lent de nombreuses étapes pour atteindre le début de la boucle. Donc, le début de la boucle est à k pas du noeud principal.

Note: Le noeud où les deux pointeurs rencontrés est k s’éloigne du début de la boucle (à l’intérieur de la boucle) et le noeud principal est également k s’éloigne du début de la boucle. boucle. Ainsi, lorsque nous avons un pointeur qui avance à un rythme égal d’un pas depuis ces deux nœuds, ils se rencontrent au début de la boucle.

Je crois que c'est simple. S'il vous plaît laissez-moi savoir si une partie est ambiguë.

4
Aadith

Bon alors supposons que le lièvre et la tortue se rencontrent à un point situé à k pas du début du cycle, le nombre d’étapes avant le début du cycle est mu et la longueur du cycle est L.

Alors maintenant, au point de rencontre ->

Distance parcourue par la tortue = mu + a * L + k - équation 1

(Mesures prises pour atteindre le début du cycle + mesures prises pour couvrir 'a' itérations du cycle + k étapes à partir du début du cycle) (où a est une constante positive)

Distance parcourue par le lièvre = mu + b * L + k - Équation 2

(Mesures prises pour atteindre le début du cycle + mesures prises pour couvrir les itérations 'b' du cycle + k étapes à partir du début du cycle) (où b est une constante positive et b> = a)

La distance supplémentaire parcourue par le lièvre est donc = Équation 2 - Équation 1 = (b-a) * L

Veuillez noter que cette distance est également égale à la distance de la tortue depuis le point de départ puisque le lièvre se déplace 2 fois plus vite que la tortue. Cela peut être assimilé à 'mu + k' qui est également la distance du point de rencontre depuis le début si nous n'incluons pas plusieurs traversées du cycle.

Ainsi, mu + k = (b-a) * L

Ainsi, mu étapes à partir de ce point ramèneraient au début du cycle (puisque k étapes depuis le début du cycle ont déjà été franchies pour atteindre le point de rencontre). Cela pourrait se produire dans le même cycle ou dans l'un des cycles suivants. Ainsi, maintenant, si nous plaçons la tortue au début de la liste chaînée, il faudra procéder par étapes afin d’atteindre le point de départ du cycle et le lièvre procéder par la suite pour atteindre également le début du cycle; point de départ du cycle.

P.S. Honnêtement, j'avais la même question que l'affiche originale dans mon esprit et j'ai lu la première réponse, ils ont effacé quelques points, mais je ne pouvais pas obtenir le résultat final clairement et j'ai donc essayé de le faire à ma façon et j'ai trouvé c'est plus facile à comprendre.

3
Prateek Jassal

enter image description herecrédit image

Distance d'appel, le nombre de liens suivis par un pointeur, et le temps, le nombre d'itérations nécessaires à l'algorithme pour déplacer le lien lent d'un point et le pointeur rapide deux liens. Il y a N nœuds avant un cycle de longueur C, étiquetés avec le décalage de cycle k = 0 à C-1.

Pour atteindre le début du cycle, lent prend N temps et distance. Cela signifie que rapide prend N distance dans le cycle (N pour y arriver, N pour tourner). Donc, au temps N, lent est au décalage de cycle k = 0 et rapide est au décalage de cycle k = N mod C.

Si N mod C est égal à zéro, lent et rapide correspondent maintenant et le cycle est trouvé à l'instant N et la position du cycle k = 0.

Si N mod C n'est pas nul, alors fast doit rattraper son retard sur lent qui, au temps N, est C- (N mod C) en retard dans le cycle.

Etant donné que la vitesse rapide se déplace de 2 pour chaque 1 lent, réduisant la distance de 1 à chaque itération, cela prend autant de temps supplémentaire que la distance entre rapide et lent au temps N, qui est C- (N mod C). Etant donné que lent se déplace depuis le décalage 0, c’est aussi le décalage où ils se rencontrent.

Donc, si N mod C est nul, la phase 1 s’arrête après N itérations au début du cycle. Sinon, la phase 1 s'arrête après N + C- (N mod C) itérations au décalage C- (N mod C) dans le cycle.

// C++ pseudocode, end() is one after last element.

int t = 0;
T *fast = begin();
T *slow = begin();
if (fast == end()) return [N=0,C=0];
for (;;) {
    t += 1;
    fast = next(fast);
    if (fast == end()) return [N=(2*t-1),C=0];
    fast = next(fast);
    if (fast == end()) return [N=(2*t),C=0];
    slow = next(slow);
    if (*fast == *slow) break;
}

Ok, donc phase 2: slow prend encore N étapes pour accéder au cycle, point auquel le rapide (se déplaçant de 1 par pas de temps) est à (C- (N mod C) + N) mod C = 0. Ils se rencontrent donc au début du cycle après la phase 2.

int N = 0;
slow = begin();
for (;;) {
    if (*fast == *slow) break;
    fast = next(fast);
    slow = next(slow);
    N += 1;
}

Pour être complet, la phase 3 calcule la durée du cycle en se déplaçant une fois de plus dans le cycle:

int C = 0;
for (;;) {
    fast = next(fast);
    C += 1;
    if (fast == slow) break;
}
2
Warren MacEvoy

enter image description here

Si les pointeurs se rencontrent en un point P comme indiqué sur la figure, la distance Z + Y est le point P et X + Y est également le point P qui signifie Z = X. C’est pourquoi garder un pointeur de P et un autre point de départ (S) jusqu’à ce qu’ils se rencontrent, c’est-à-dire déplacer une distance égale (Z ou X) vers le même point M (distance Z de P et X de S). début de la boucle. Simple!

1
user9639921

Réduisez le problème en un problème de boucle, puis revenez au problème initial

Je trouve l'explication suivante plus intuitive.

  1. Prenez deux pointeurs ( 1 = tortue et 2 = lièvre) qui commencent de la tête ( [~ # ~] o [~ # ~] ), 1 a une longueur de pas de 1 , 2 a un longueur de pas de 2 . Pensez au moment où 1 atteint le nœud de départ de ce cycle ( [~ # ~] a [~ # ~] ).

    Nous voulons répondre à la question suivante "Où est 2 lorsque 1 est dans A?" .

    Donc, OA = a Est un nombre naturel (a >= 0). Mais cela peut être écrit de la manière suivante: a = k*n + b, Où a, k, n, b are natural numbers:

    • n = la durée du cycle
    • k >= 0 = Constant
    • 0 <= b <= n-1

    Cela signifie que b = a % n.

    Exemple: si a = 20 Et n = 8 => k = 2 Et b = 4 Car 20 = 2*8 + 4.

    La distance parcourue par 1 est de d = OA = a = k*n + b. Mais dans le même temps, 2 couvre D = 2*d = d + d = OA + d = OA + k*n + b. Cela signifie que lorsque 2 est en A, il doit couvrir k*n + b. Comme vous pouvez le voir, k est le nombre de tours, mais après ces tours, 2 sera b loin de A. Nous avons donc trouvé où 2 est le moment où 1 est en A. Appelons ce point B, où AB = b.

    enter image description here

  2. Maintenant, nous réduisons le problème à un cercle. La question est "Où est le point de rencontre?" . Où est ce [~ # ~] c [~ # ~] ?

    enter image description here

    À chaque étape, 2 réduit la distance de 1 avec 1 (Disons mètre) car 1 s’éloigne de 2 avec 1, mais en même temps 2 se rapproche de 1 par 2.

    Ainsi, l'intersection sera lorsque la distance entre 1 et 2 sera être zéro. Cela signifie que 2 réduit la distance n - b. Pour ce faire, 1 effectuera des pas de n - b, Tandis que 2 fera 2*(n - b) étapes.

    Donc, le point d'intersection sera n - b Loin de [~ # ~] et [~ # ~] (dans le sens des aiguilles d'une montre), car est la distance parcourue par 1 jusqu'à ce qu'elle rencontre 2 . => la distance entre [~ # ~] c [~ # ~] et [~ # ~] a [~ # ~] est CA = b, car AC = AB + BC = n - b et CA = n - AC. Ne pensez pas que AC = CA, Car la distance AC n'est pas une distance mathématique triviale, c'est le nombre de pas entre [~ # ~] a [~ # ~] et [~ # ~] c [~ # ~] (où [~ # ~] a [~ # ~] est le point de départ et [~ # ~] c [~ # ~] est le point final).

  3. Revenons maintenant au schéma initial.

    Nous savons que a = k*n + b Et CA = b.

    On peut prendre 2 nouveaux pointeurs 1 ' et 1' ', où 1 ' part de la tête ( [~ # ~] o [~ # ~] ) et 1 '' part du point d'intersection ( [~ # ~] c [~ # ~] ).

    Alors que 1 ' va de [~ # ~] o [~ # ~] à [~ # ~] a [~ # ~] , 1 '' va de [~ # ~] c [~ # ~] à [~ # ~] a [~ # ~] et continue à finir k tours. Ainsi, le point d'intersection est [~ # ~] a [~ # ~] .

    enter image description here

    enter image description here

1
ROMANIA_engineer

Il existe déjà de nombreuses réponses à cette question, mais j’ai un jour proposé un schéma plus intuitif pour moi. Peut-être que cela peut aider d'autres personnes.

Les principaux moments aha pour moi ont été:

  • Diviser [~ # ~] t [~ # ~] (tortue) en T1 (pré-boucle) et T2 = (en boucle). T = tortoise, H = hare

  • Soustrayez [~ # ~] t [~ # ~] de [~ # ~] h [~ # ~], où ils se chevauchent visuellement. Ce qui reste ( H - T = H ') est égal à [~ # ~] t [~ # ~].

  • Les calculs restants sont assez simples. From H, subtract where T visually overlaps
0
mhelvens

-il y a k pas avant la boucle. Nous ne savons pas ce que k est et n'avons pas besoin de le savoir. Nous pouvons travailler abstraitement avec juste k.

--Après k étapes

----- T est au début du cycle

----- H est k pas dans le cycle (il est allé 2k total et donc k dans la boucle)

** ils sont maintenant en boucle - k séparés

(notez que k == K == mod (loopsize, k) - eg si un nœud est à 2 étapes dans un cycle à 5 nœuds, il est également de 7, 12 ou 392 étapes, donc la longueur du cycle n'est pas k facteur de.

Puisqu'ils se rattrapent au rythme d'un pas par unité de temps car l'un se déplace deux fois plus vite que l'autre, ils se rencontreront à la taille de boucle - k.

Cela signifie qu'il faudra k nœuds pour atteindre le début du cycle et donc que la distance de tête à cyclestart et de collision à cyclestart soit la même.

Alors maintenant, après la première collision, revenez à T. T et H se rencontreront à cyclestart si vous vous déplacez au taux de 1 chacun. (en k étapes pour les deux)

Cela signifie que l'algorithme est:

  • du mouvement de la tête T = t.next et H.next.next jusqu'à ce qu'ils entrent en collision (T == H) (il y a un cycle)

// prend en charge le cas où k = 0 ou T et H rencontrés en tête de la boucle en calculant la longueur de la boucle

--compte la longueur du cycle en déplaçant T ou H autour avec un compteur

- déplace un pointeur T2 en tête de liste

--déplace la longueur du pointeur des étapes du cycle

--move un autre pointeur H2 à la tête

- déplacez T2 et H2 en tandem jusqu'à ce qu'ils se rencontrent au début du cycle

c'est ça!

0
Droid Teahouse

Je ne pense pas que ce soit vrai que quand ils se rencontrent, c'est le point de départ. Mais oui, si l’autre pointeur (F) était au point de rendez-vous auparavant, alors ce pointeur se trouvera à la fin de la boucle au lieu du début de la boucle et du pointeur (S) qui est parti du début de la liste, se retrouver au début de la boucle. pour par exemple:

1->2->3->4->5->6->7->8->9->10->11->12->13->14->15->16->17->18->19->20->21->22->23->24->8

Meet at :16

Start at :8

public Node meetNodeInLoop(){

    Node fast=head;
    Node slow=head;

    fast=fast.next.next;
    slow=slow.next;

    while(fast!=slow){

        fast=fast.next;
        fast=fast.next;

        if(fast==slow) break; 

        slow=slow.next;
    }

    return fast;

}

public Node startOfLoop(Node meet){

    Node slow=head;
    Node fast=meet;

    while(slow!=fast){
        fast=fast.next;
        if(slow==fast.next) break;
        slow=slow.next;
    }

    return slow;
}
0
MrA

Travailler cela avec un diagramme pourrait aider. J'essaie d'expliquer le problème sans équations.

  1. Si nous laissons le lièvre et la tortue courir en cercle et que le lièvre court deux fois la tortue, alors, au bout d'un tour, la tortue lièvre serait à moitié. Au bout de deux tours de tortue lièvre aurait fait 1 tour et ils se rencontrent tous les deux. Cela s'applique à toutes les vitesses, comme si le lièvre courait trois fois, le lièvre 1 tour équivaut à 1/3 de la tortue, donc au bout de 3 tours, le lièvre aurait couvert un tour et ils se seraient rencontrés.
  2. Maintenant, si nous les commençons m avant la boucle, cela signifie que le lièvre le plus rapide commence en boucle. Donc, si les tortues atteignent le début de la boucle, le lièvre est m pas en avant et quand elles se rencontrent, ce sera m avant le début de la boucle.
0
shiva kumar

Avec toutes les analyses ci-dessus, si vous êtes une personne qui apprend par l'exemple, j'ai essayé de rédiger une courte analyse et un exemple qui aide à expliquer les calculs que tout le monde a tenté d'expliquer. Et c'est parti!

Analyse:

Si nous avons deux pointeurs, l'un plus rapide que l'autre, et que nous les déplaçons ensemble, ils se retrouveront éventuellement de nouveau pour indiquer un cycle ou nuls pour indiquer l'absence de cycle.

Pour trouver le point de départ du cycle, laissez ...

  1. m soit la distance entre la tête et le début du cycle;
  2. d soit le nombre de nœuds du cycle;
  3. p1 soit la vitesse du pointeur le plus lent;
  4. p2 soit la vitesse du pointeur le plus rapide, par exemple. 2 signifie étapes à travers deux nœuds à la fois.

    Observez les itérations suivantes:

 m = 0, d = 10:
 p1 = 1:  0  1  2  3  4  5  6  7  8  9 10 // 0 would the start of the cycle
 p2 = 2:  0  2  4  6  8 10 12 14 16 18 20

 m = 1, d = 10:
 p1 = 1: -1  0  1  2  3  4  5  6  7  8  9
 p2 = 2: -1  1  3  5  7  9 11 13 15 17 19

 m = 2, d = 10:
 p1 = 1: -2 -1  0  1  2  3  4  5  6  7  8
 p2 = 2: -2  0  2  4  6  8 10 12 14 16 18

À partir des exemples de données ci-dessus, nous pouvons facilement découvrir que chaque fois que les pointeurs les plus rapides et les plus lents se rencontrent, ils sont m à quelques pas du début du cycle. Pour résoudre ce problème, replacez le pointeur le plus rapide en tête et réglez sa vitesse sur la vitesse du pointeur le plus lent. Quand ils se retrouvent, le nœud est le début du cycle.

0
Steve

Une explication simple utilisant l'idée de vitesse relative enseignée au lycée - Cours de physique 101/cinématique.

Circle in LinkedList

  1. Supposons que la distance entre le début de la liste liée et le début du cercle est x Hops. Appelons le début du cercle sous le point X (en majuscules - voir la figure ci-dessus). Supposons également que la taille totale du cercle est N Hops.

  2. Vitesse du lièvre = 2 * Vitesse de la tortue. C'est donc 1 Hops/sec et 2 Hops/sec respectivement

  3. Lorsque la tortue atteint le début du cercle X, le lièvre doit encore être x s'éloigne au point Y de la figure. (Parce que le lièvre a parcouru deux fois plus de distance que la tortue).

  4. Ainsi, la longueur de l’arc restant dans le sens horaire de X à Y serait de N-x. T sa se trouve également être la distance relative à couvrir entre le lièvre et la tortue pour pouvoir se rencontrer . Disons que cette distance relative sera couverte dans le temps t_m c'est-à-dire le temps de se rencontrer. La vitesse relative est (2 Hops/sec - 1 Hops/sec) c'est à dire. 1 Hops/sec. Ainsi, en utilisant, distance relative = vitesse relative X fois, nous obtenons, t = N-x sec. Donc ça va prendre N-x pour atteindre le point de rencontre de la tortue et du lièvre.

  5. Maintenant en N-xsecondes et à 1 Hops/sec _ _ rapidité, la tortue qui était auparavant au point X couvrira N-x Hops pour atteindre le point de rendez-vous M. Donc, cela signifie que le point de rencontre M est à N-x _ Saute dans le sens anti-horaire de X = (ce qui implique encore) => qu’il reste x distance restante du point M à X dans le sens horaire.

  6. Mais x est aussi la distance pour atteindre le point X à partir du début de la liste liée.

  7. Maintenant, nous ne nous soucions pas du nombre de Hops x correspondant. Si nous plaçons une tortue au début de la LinkedList et une tortue au point de rencontre M et les laissons sauter/marcher, elles se rencontreront au point X, qui est le point (ou noeud) dont nous avons besoin.

0
Pranjal Mittal

disons,

N[0] is the node of start of the loop, 
m is the number of steps from beginning to N[0].

nous avons 2 pointeurs A et B, A tourne à la vitesse 1x, B à la vitesse 2x, les deux commencent au début.

quand A atteint N [0], B devrait être déjà dans N [m]. (Remarque: A utilise m étapes pour atteindre N [0] et B doit être m étapes plus loin)

Ensuite, A exécute k autres étapes pour entrer en collision avec B, c’est-à-dire que A est situé à N [k], B est situé à N [m + 2k] (Remarque: B doit exécuter 2k étapes à partir de N [m]).

Une collision B à N [k] et N [m + 2k] respectivement, cela signifie que k = m + 2k, donc k = -m

Ainsi, pour revenir au N [0] de N [k], nous avons besoin de m plus d’étapes.

Simplement dire, il nous faut simplement exécuter plusieurs étapes après avoir trouvé le nœud de collision. Nous pouvons avoir un pointeur à courir depuis le début et un pointeur allant du nœud de collision, ils se rencontreront à N [0] après m étapes.

Par conséquent, les pseudo-codes sont les suivants:

1) A increase 1 step per loop
2) B increase 2 steps per loop
3) if A & B are the same node, cycle found, then go to 5
4) repeat from 1
5) A reset to head
6) A increase 1 step per loop
7) B increase 1 step per loop
8) if A & B are the same node, start of the cycle found
9) repeat from 6
0