détecter le début d'une boucle dans un seul liés liste de liens?
Est-il possible de trouver le début d'une boucle dans une liste de liens à l'aide de pas plus de deux pointeurs?
Je ne veux pas de visiter chaque nœud et marquer vu et reporting le premier nœud déjà été vu.Est-il un autre moyen pour ce faire?
- est-ce devoirs?
- Cela a été demandé avant? google.com/...
- Double Possible de Expliquer comment trouver du début du cycle de nœud dans le cycle lié liste de travail?
Vous devez vous connecter pour publier un commentaire.
J'ai entendu cette question exacte que d'une entrevue questionnaire.
La solution la plus élégante est:
Mettre les deux pointeurs au premier élément (appelons les A et B)
Puis continuer boucle::
Chaque fois que vous mettez à jour un pointeur, vérifiez si A et B sont identiques.
Si, à un certain point de pointeurs A et B sont identiques, alors vous avez une boucle.
Le problème avec cette approche est que vous pouvez vous retrouver en mouvement autour de la boucle deux fois, mais pas plus de deux fois avec Un pointeur
Si vous voulez à réellement trouver l'élément qui a deux pointeurs pointant vers elle, ce qui est plus difficile. Je sortait d'une branche et dire que ses impossible de le faire avec seulement deux pointeurs, sauf si vous êtes prêt à répéter à la suite de la liste liée à un grand nombre de fois.
Le moyen le plus efficace de le faire avec plus de mémoire, serait de mettre les liens vers les éléments de la matrice et, à les trier, puis regarder pour une répétition.
Etape 1: Procéder de la manière habituelle, vous allez utiliser pour trouver la boucle, c'est à dire
Deux pointeurs, l'incrément de un en seule étape et d'autres en deux étapes, Si elles remplissent toutes les deux dans un moment, il y a une boucle.
Etape 2: Geler un pointeur à l'endroit où il était et l'incrément de l'autre pointeur dans une étape de comptage les étapes que vous faites et quand ils rencontrer à nouveau, le comte va vous donner la longueur de la boucle (c'est même en comptant le nombre d'éléments dans une circulaire de liste des liens).
Etape 3: Réinitialiser les deux pointeurs vers le début de la liste des liens, incrémenter un pointeur à la longueur de la boucle de fois et puis commencer le deuxième pointeur. incrément de deux pointeurs en une seule étape, et quand ils se rencontrent à nouveau, ce sera le début de la boucle (c'est la même chose que de trouver les nème de l'élément à partir de la fin de la liste des liens).
PREUVE MATHÉMATIQUE + LA SOLUTION
CAS SIMPLE: Lorsque k < N
Lorsque le pointeur " P " serait à BEGINLOOP (c'est à dire qu'il aurait voyagé 'k' étapes), Q aurait voyagé '2k' étapes. Oui, effectivement, Q est en avance de '2k-k = k', étapes de P lorsque P entre dans la boucle, et donc Q est 'n-k' pas derrière la BEGINLOOP maintenant.
Lorsque P aurait déplacé de BEGINLOOP à MEETPONT, il aurait voyagé "m-k' étapes. En ce moment, Q aurait voyagé '2(m-k)' étapes. Mais, depuis, ils ont rencontré, et Q commencé "n-k" pas derrière la BEGINLOOP, oui, effectivement,
'2(m-k) (n-k)' doit être égal à '(m-k)'
Donc,
QUI SIGNIFIE, P et Q satisfont au point égal au nombre d'étapes (ou plusieurs pour être général, voir le cas mentionné ci-dessous) dans la boucle. Maintenant, à la MEETPOINT, à la fois P et Q sont 'n-(m-k) les mesures prises par derrière, j'.e, 'k', pas derrière ,comme nous l'avons vu, n=m.
Donc, si nous commençons à P à partir de l'en-TÊTE de nouveau, et Q à partir de la MEETPOINT mais cette fois avec le rythme égal à P, P et Q seront désormais réunion à BEGINLOOP seulement.
CAS GÉNÉRAL: Dire, k = nX + Y, Y < n
(D'où, k%n = Y)
Lorsque le pointeur " P " serait à BEGINLOOP (c'est à dire qu'il aurait voyagé 'k' étapes), Q aurait voyagé '2k' étapes. Oui, effectivement, Q est en avance de '2k-k = k', étapes de P lorsque P entre dans la boucle. Mais, veuillez noter " k "est supérieure à "n", ce qui signifie Q aurait fait plusieurs tours de la boucle. Oui, effectivement, Q est 'n-(k%n)' pas derrière la BEGINLOOP maintenant.
Lorsque P aurait déplacé de BEGINLOOP à MEETPOINT, il aurait voyagé "m-k' étapes. (D'où, effectivement, MEETPOINT serait à l' "(m-k)%n' pas d'avance de BEGINLOOP maintenant.) En ce moment, Q aurait voyagé '2(m-k)' étapes. Mais, depuis, ils ont rencontré, et Q commencé 'n-(k%n)' pas derrière la BEGINLOOP, oui, effectivement, la nouvelle position de Q (qui est '(2(m-k) (n-k/%n)%n "de BEGINLOOP) doit être égale à la nouvelle position de P (qui est "(m-k)%n' depuis le début de la BOUCLE).
Donc,
Nous avons d'abord essayer de trouver, est-il une boucle dans la liste ou pas. Si la boucle existe alors nous essayons de trouver le point de départ de la boucle. Pour cela, nous utilisons deux pointeurs à savoir slowPtr et fastPtr. Dans la première détection (vérification de la boucle for), fastPtr se déplace de deux étapes à la fois, mais slowPtr se déplace en avance d'une étape à la fois.
Il est clair que si il y a une boucle dans la liste puis ils rencontreront au point (Point 7 de l'image ci-dessus), parce que fastPtr pointeur est en cours d'exécution deux fois plus rapide que l'autre.
Maintenant, nous arrivons à un deuxième problème de trouver le point de départ de la boucle.
Supposons, ils se réunissent au Point 7 (comme indiqué dans l'image ci-dessus). Ensuite, slowPtr sort de la boucle et se tient au début de la liste des moyens au Point 1, mais fastPtr encore au point de rencontre (Point 7). Maintenant nous comparons les deux pointeurs de la valeur, s'ils le même, alors il est le point de départ de la boucle sinon on se déplacer d'une étape à l'avance (ici fastPtr est également le déplacement d'un pas à chaque fois) et de les comparer à nouveau jusqu'à ce que nous trouver en un même point.
Maintenant, une question me vient à l'esprit, comment est-il possible. Il existe donc bien une preuve mathématique.
Supposons que:
Plus de détails ici
m+q(l)+k=2*(m+p(l)+k)
=>m+k=q(l)-2*p(l)
Procéder de la manière habituelle, vous allez utiliser pour trouver la boucle. c'est à dire. Deux pointeurs, l'incrément de un en seule étape(slowPointer) et d'autres en deux étapes(fastPointer), Si elles remplissent toutes les deux dans un moment, il y a une boucle.
Comme vous pouvez l'avez déjà compris que le point de rencontre est k Étape avant que le chef de la boucle.
où k est la taille de la non-boucle partie de la liste.
maintenant, déplacez lent à la tête de la boucle
maintenir Rapide au point de collision
chacun d'entre eux sont k Étape depuis le début de la boucle (Lent du début de la liste où que rapide est k étape avant que le chef de la boucle - Dessiner l'image pour obtenir le plus de clarté)
Maintenant déplacer à la même vitesse - Ils doivent se rencontrer au début de la boucle
par exemple
C'est le code pour trouver de début de boucle dans la Liste liée :
Il y a deux façon de trouver des boucles dans une liste de liens.
1. L'utilisation de deux pointeur d'une avance d'un pas et autres avances de deux étapes, si il est en boucle, dans un moment, les deux pointeur obtenir la même valeur et ne jamais atteindre la valeur null. Mais si il n'y a pas de boucle de pointeur atteint nulle en un point et deux pointeur de ne jamais obtenir la même valeur. Mais dans cette approche, nous pouvons obtenir il y a une boucle dans le lien de la liste, mais nous ne pouvons pas dire où exactement le démarrage de la boucle. Ce n'est pas le moyen efficace ainsi.
Et bien j'ai essayé une manière en utilisant un pointeur... j'ai essayé la méthode dans plusieurs jeux de données.... Comme la mémoire de chacun des nœuds de la liste sont attribués dans un ordre croissant, de sorte que tout en parcourant la liste liée à partir de la tête de la liste chaînée, si l'adresse d'un nœud devient plus grande que l'adresse du nœud qu'il désigne, nous pouvons déterminer qu'il n'y est une boucle, ainsi que le début de l'élément de la boucle.
La meilleure réponse que j'ai trouvé est ici:
tianrunhe: trouvez-boucle-point de départ-dans-un-circulaire-liste liée
p1 déplace à V, et p2 se déplaçant à 2*V
lorsque les 2 pointeurs de répondre: distance parcourue est de = m+ n*L-d = 2*(m+ L-d)
=> ce qui signifie (pas mathematicaly démontré ici) que si p1 commence à partir de la TÊTE & p2 commence à partir de MEETING_POINT & ils se déplacent à la même vitesse, ils vont rencontrer @ START_LOOP
Reportez-vous à cette lien pour la réponse complète.
Procéder de la manière habituelle, vous allez utiliser pour trouver la boucle. c'est à dire. Deux pointeurs, l'incrément de un en seule étape et d'autres en deux étapes, Si elles remplissent toutes les deux dans un moment, il y a une boucle.
Conserver l'un des pointeurs fixes obtenir le nombre total de nœuds dans la boucle de dire L.
Maintenant à partir de ce point(incrément deuxième pointeur vers le nœud suivant dans la boucle) dans la boucle inverse de la liste, et de compter le nombre de nœuds traversés, dire X.
Maintenant, en utilisant la deuxième pointeur(la boucle est cassé) à partir du même point dans la boucle travrse la liste, et de compter le nombre de nœuds restants dire Y
La boucle commence après la ((X+Y)-L)\2 nœuds. Ou il commence à l' (((X+Y)-L)\2+1)ème nœud.
Procéder de la manière habituelle, vous allez utiliser pour trouver la boucle. c'est à dire. Deux pointeurs, l'incrément de un en seule étape et d'autres en deux étapes, Si elles remplissent toutes les deux dans un moment, il y a une boucle.
Conserver l'un des pointeurs fixes obtenir le nombre total de nœuds dans la boucle de dire L.
Maintenant à partir de ce point(incrément deuxième pointeur vers le nœud suivant dans la boucle) dans la boucle inverse de la liste, et de compter le nombre de nœuds traversés, dire X.
Maintenant, en utilisant la deuxième pointeur(la boucle est cassé) à partir du même point dans la boucle travrse la liste, et de compter le nombre de nœuds restants dire Y
La boucle commence après la ((X+Y)-L)\2 nœuds. Ou il commence à l' (((X+Y)-L)\2+1)ème nœud.