Entiendo que la reunión de Tortuga y Liebre concluye la existencia del bucle, pero ¿cómo se mueve la tortuga al comienzo de la lista vinculada mientras se mantiene a la liebre en el lugar de reunión, seguido de mover ambos un paso a la vez para que se encuentren en el punto de inicio del ciclo?
algorithm
linked-list
cycle
floyd-cycle-finding
Programador apasionado
fuente
fuente
Respuestas:
Este es el algoritmo de Floyd para la detección de ciclos . Estás preguntando acerca de la segunda fase del algoritmo: una vez que hayas encontrado un nodo que es parte de un ciclo, ¿cómo se encuentra el inicio del ciclo?
En la primera parte del algoritmo de Floyd, la liebre mueve dos pasos por cada paso de la tortuga. Si la tortuga y la liebre alguna vez se encuentran, hay un ciclo, y el punto de encuentro es parte del ciclo, pero no necesariamente el primer nodo del ciclo.
Cuando la tortuga y la liebre se encuentran, hemos encontrado la i más pequeña (el número de pasos dados por la tortuga) tal que X i = X 2i . Deje que mu represente el número de pasos para llegar de X 0 al comienzo del ciclo, y deje que lambda represente la duración del ciclo. Entonces i = mu + a lambda, y 2i = mu + b lambda, donde a y b son enteros que indican cuántas veces la tortuga y la liebre dieron la vuelta al ciclo. Restando la primera ecuación de la segunda da i = (ba) * lambda, entonces yo es un múltiplo entero de lambda. Por lo tanto, X i + mu = X mu . X i representa el punto de encuentro de la tortuga y la liebre. Si mueve la tortuga de regreso al nodo inicial X0 , y deje que la tortuga y la liebre continúen a la misma velocidad, después de mu pasos adicionales, la tortuga habrá alcanzado X mu , y la liebre habrá alcanzado X i + mu = X mu , por lo que el segundo punto de encuentro indica el inicio de la ciclo.
fuente
X_mu
inicio del ciclo (por definición de mu). Luego, si realiza más pasos, donde i es un múltiplo de la duración del ciclo, termina de nuevo al inicio del ciclo:X_mu + i
=X_mu
. Pero la suma es conmutativa, por lo que es equivalente a tomar i pasos para llegar desde el inicio hasta el primer punto de encuentroX_i
, luego, pasos adicionales para volver alX_mu
inicio del ciclo.i
está en algún punto del ciclo, creo que la ecuación debería seri = mu + k + a*lambda
y2i = mu + k + b*lambda
dóndek
está el número de pasos desde el inicio del ciclo hasta el punto de encuentro. Sin embargo, restar ambas ecuaciones da el mismo resultado.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 unosm
pasos del ciclo. También digamos que el punto de encuentro está ak
pasos del comienzo del ciclo y la tortuga y la liebre se encuentran cuando la tortuga ha dado losi
pasos totales. (Hare habría dado2i
pasos totales para entonces).Las siguientes 2 condiciones deben cumplir:
El primero dice que la tortuga mueve
i
pasos y en estosi
pasos primero llega al ciclo. Luego pasa por losp
tiempos de ciclo para algún número positivop
. Finalmente, pasa pork
más nodos hasta que se encuentra con la liebre.Un similar es cierto para la liebre. Mueve los
2i
pasos y en estos2i
pasos primero llega al ciclo. Luego pasa por losq
tiempos de ciclo para algún número positivoq
. Finalmente, pasa pork
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,
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:
Podemos verificar que estos valores funcionen de la siguiente manera:
Para este conjunto,
i
esPor 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.
fuente
m + k = (q - 2p) n
se puede simplificar aún másm + k = q*n
. Esto se debe a que el número de bucles que la tortuga toma siempre será cero, ya que la liebre nunca puede alcanzar a la tortuga sin conocerla. Piénsalo.Refiera esta imagen:
Distancia recorrida por slowPointer antes de la reunión = x + y
Distancia recorrida por el puntero rápido antes de la reunión = (x + y + z) + y = x + 2y + z
Dado que fastPointer viaja con el doble de velocidad que 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 2 (x + y) = x + 2y + z => x + 2y + z = 2x + 2y => x = z
Por lo tanto, moviendo slowPointer para comenzar la lista vinculada y haciendo que slowPointer y fastPointer muevan un nodo a la vez, ambos tienen la misma distancia que cubrir .
Llegarán al punto donde comienza el ciclo en la lista vinculada.
fuente
La respuesta simple y subestimada de Old Monk explica cómo encontrar el ciclo cuando el corredor rápido completa solo un ciclo completo. En esta respuesta, explico el caso cuando el corredor rápido ha ejecutado el ciclo varias veces antes de que el corredor lento entre en el ciclo.
Usando la misma imagen:
Digamos que el corredor rápido ha corrido el bucle m veces antes de encontrarse lento y rápido. Esto significa que:
Dado que las carreras rápidas tienen el doble de velocidad que las lentas, y que han estado funcionando durante el mismo tiempo, implica que si duplicamos la distancia recorrida lentamente, obtenemos la distancia recorrida rápidamente. Así,
Resolviendo para x da,
En un escenario real significaría, x = (m - 1) ejecuciones completas del bucle + una distancia adicional z .
Por lo tanto, si colocamos un puntero al comienzo de la lista y dejamos el otro en el punto de encuentro, moverlos a la misma velocidad dará como resultado que el puntero en bucle complete m - 1 carreras del bucle y luego se encuentre con el otro puntero justo al comienzo del bucle.
fuente
Es muy muy simple. Puedes pensar en términos de velocidad relativa. Si el conejo mueve dos nodos y la tortuga mueve un nodo, en relación con la tortuga el conejo mueve un nodo (suponga que la tortuga está en reposo). Entonces, si movemos un nodo en la lista enlazada circular, seguramente nos encontraremos en ese punto nuevamente.
Después de encontrar el punto conectado dentro de la lista enlazada circular, ahora el problema se reduce a encontrar el punto de intersección de dos problemas de la lista enlazada.
fuente
En el momento de la primera colisión, la tortuga se movió m + k pasos como se muestra arriba. La liebre se mueve dos veces más rápido que la tortuga, lo que significa que la liebre se movió 2 (m + k) pasos. De estos simples hechos podemos derivar el siguiente gráfico.
En este punto, volvemos a mover a la tortuga al inicio y declaramos que tanto la liebre como la tortuga deben moverse paso a paso. Por definición, después de m pasos, la tortuga estará al comienzo del ciclo. ¿Dónde estará la liebre?
La liebre también estará al comienzo del ciclo. Esto queda claro en el segundo gráfico: cuando la tortuga se movió de regreso al inicio, la liebre fue k pasos en su último ciclo. Después de m pasos, la liebre habrá completado otro ciclo y colisionado con la tortuga.
fuente
Acercarse:
Hay dos punteros:
Si los dos punteros se encuentran, demuestra que hay un bucle. Una vez que se hayan encontrado, uno de los nodos apuntará a la cabeza y luego ambos avanzarán un nodo a la vez. Se encontrarán al comienzo del ciclo.
Justificación: Cuando dos personas caminan por una pista circular, una de ellas al doble de la velocidad de la otra, ¿dónde se encuentran? Exactamente donde comenzaron.
Ahora, supongamos que el corredor rápido tiene una ventaja inicial de
k
pasos en unan
vuelta. ¿Dónde se encontrarán? Exactamente en losn-k
pasos. Cuando el corredor lento ha cubierto los(n-k)
pasos, el corredor rápido habría cubierto losk+2(n-k)
pasos. ( es decir,k+2n-2k
pasos , es decir,2n-k
pasos ). es decir(n-k)
pasos (el camino es circular y no nos preocupa el número de rondas después de las cuales se encuentran; solo nos interesa la posición en la que se encuentran).Ahora, ¿cómo consiguió el corredor rápido la ventaja de los
k
pasos en primer lugar? Porque le tomó al corredor lento tantos pasos para llegar al inicio del ciclo. Entonces, el inicio del ciclo es k pasos desde el nodo principal.Nota: El nodo donde se encontraron ambos punteros está a
k
pasos del inicio del ciclo (dentro del ciclo) y el nodo principal también está ak
pasos del inicio del ciclo. Entonces, cuando tengamos el puntero avanzando a un ritmo igual de 1 paso desde estos nodos, se encontrarán al comienzo del ciclo.Creo que es sencillo. Avíseme si alguna parte es ambigua.
fuente
Bien, supongamos que la liebre y la tortuga se encuentran en un punto que está a k pasos del comienzo del ciclo, el número de pasos antes de que comience el ciclo es mu y la duración del ciclo es L.
Así que ahora en el punto de encuentro ->
Distancia cubierta por la tortuga = mu + a * L + k - Ecuación 1
(Pasos para alcanzar el comienzo del ciclo + pasos para cubrir las iteraciones 'a' del ciclo + k pasos desde el inicio del ciclo) (donde a es una constante positiva)
Distancia recorrida por la liebre = mu + b * L + k - Ecuación 2
(Pasos para alcanzar el comienzo del ciclo + pasos para cubrir las iteraciones 'b' del ciclo + k pasos desde el inicio del ciclo) (donde b es una constante positiva yb> = a)
Entonces, la distancia adicional cubierta por la liebre es = Ecuación 2 - Ecuación 1 = (ba) * L
Tenga en cuenta que esta distancia también es igual a la distancia de la tortuga desde el punto de partida ya que la liebre se mueve 2 veces más rápido que la tortuga. Esto puede equipararse a 'mu + k', que también es la distancia del punto de encuentro desde el principio si no incluimos múltiples recorridos del ciclo.
Por lo tanto, mu + k = (ba) * L
Entonces, mis pasos desde este punto llevarían de regreso al comienzo del ciclo (ya que k pasos desde el comienzo del ciclo ya se han tomado para llegar al punto de encuentro). Esto podría suceder en el mismo ciclo o en cualquiera de los ciclos posteriores. Por lo tanto, ahora si movemos la tortuga al comienzo de la lista vinculada, tomará mu pasos para llegar al punto de inicio del ciclo y la liebre tomaría mu pasos para también alcanzar el comienzo del ciclo y así ambos se encontrarían en el punto de partida del ciclo.
PD Honestamente, tenía la misma pregunta que el póster original en mi mente y leí la primera respuesta, aclararon algunas cosas, pero no pude llegar al resultado final con claridad, así que intenté hacerlo a mi manera y Me resultó más fácil de entender.
fuente
credito de imagen
La distancia de la llamada al número de enlaces que sigue un puntero, y el tiempo al número de iteraciones que toma el algoritmo para mover el puntero lento un enlace y el puntero rápido dos enlaces. Hay N nodos antes de un ciclo de longitud C, etiquetados con desplazamiento de ciclo k = 0 a C-1.
Para alcanzar el inicio del ciclo, lento toma N tiempo y distancia. Esto significa que rápido toma N distancia en el ciclo (N para llegar allí, N para girar). Entonces, en el momento N, lento está en el desplazamiento del ciclo k = 0, y rápido está en el desplazamiento del ciclo k = N mod C.
Si N mod C es cero, lento y rápido ahora coinciden y el ciclo se encuentra en el momento N y la posición del ciclo k = 0.
Si N mod C no es cero, entonces rápido ahora tiene que ponerse al día con lento, que en el momento N es C- (N mod C) distancia atrás en el ciclo.
Dado que los movimientos rápidos 2 por cada 1 de lento, reduciendo la distancia en 1 en cada iteración, esto toma tanto tiempo adicional como la distancia entre rápido y lento en el tiempo N, que es C- (N mod C). Como lento se mueve desde el desplazamiento 0, este también es el desplazamiento donde se encuentran.
Entonces, si N mod C es cero, la fase 1 se detiene después de N iteraciones al comienzo del ciclo. De lo contrario, la fase 1 se detiene después de las iteraciones N + C- (N mod C) en el desplazamiento C- (N mod C) en el ciclo.
Ok, entonces la fase 2: lento toma N más pasos para llegar al ciclo, en cuyo punto rápido (ahora moviéndose 1 por paso de tiempo) está en (C- (N mod C) + N) mod C = 0. Entonces se encuentran al comienzo del ciclo después de la fase 2.
Para completar, la fase 3 calcula la duración del ciclo moviéndose una vez más a través del ciclo:
fuente
Reduzca el problema a un problema de bucle, luego regrese al problema inicial
Encuentro la siguiente explicación más intuitiva.
Tome dos punteros ( 1 = tortuga y 2 = liebre) que comienzan desde la cabeza ( O ), 1 tiene una longitud de paso de 1 , 2 tiene una longitud de paso de 2 . Piense en el momento en que 1 alcanza el nodo de inicio de ese ciclo ( A ).
Queremos responder a la siguiente pregunta "¿Dónde está 2 cuando 1 está en A?".
Entonces,
OA = a
es un número natural (a >= 0
). Pero se puede escribir de la siguiente manera:,a = k*n + b
dondea, k, n, b are natural numbers
:n
= la duración del ciclok >= 0
= constante0 <= b <= n-1
Esto significa que
b = a % n
.Por ejemplo: si
a = 20
yn = 8
=>k = 2
yb = 4
porque20 = 2*8 + 4
.La distancia recorrida por 1 es
d = OA = a = k*n + b
. Pero al mismo tiempo, 2 cubiertasD = 2*d = d + d = OA + d = OA + k*n + b
. Esto significa que cuando 2 está en A tiene que cubrirsek*n + b
. Como se puede ver,k
es el número de vueltas, pero después de esas vueltas, 2 será b lejos de A. Así, encontramos, donde 2 es cuando 1 se encuentra en la llamada de A. Let ese puntoB
, dondeAB = b
.Ahora, reducimos el problema a un círculo. La pregunta es "¿Dónde está el punto de encuentro?" . ¿Dónde está esa C ?
En cada paso, 2 reduce la distancia de 1 con
1
(digamos metro) porque 1 se aleja de 2 con1
, pero al mismo tiempo 2 se acerca a 1 por2
.Entonces, la intersección será cuando la distancia entre 1 y 2 sea cero. Esto significa que 2 reduce la
n - b
distancia. Para lograr esto, 1 harán - b
pasos, mientras que 2 hará2*(n - b)
pasos.Entonces, el punto de intersección estará
n - b
lejos de A (en el sentido de las agujas del reloj), porque esta es la distancia cubierta por 1 hasta que se encuentra con 2 . => la distancia entre C y A esCA = b
, porqueAC = AB + BC = n - b
yCA = n - AC
. No piense queAC = CA
, debido a que laAC
distancia no es una distancia matemática trivial, es el número de pasos entre A y C (donde A es el punto de inicio y C es el punto final).Ahora, volvamos al esquema inicial.
Lo sabemos
a = k*n + b
yCA = b
.Podemos tomar 2 punteros nuevos 1 ' y 1' ' , donde 1' comienza desde la cabeza ( O ) y 1 '' comienza desde el punto de intersección ( C ).
Mientras 1 ' va de O a A , 1' ' va de C a A y continúa terminando
k
vueltas. Por lo tanto, el punto de intersección es una .fuente
Si los punteros se encontraron en un punto P como se muestra en la figura, la distancia Z + Y es el punto P y X + Y también es el punto P, lo que significa Z = X. Es por eso que seguir moviendo un puntero desde P y moviendo otro desde el inicio (S) hasta que se encuentran, lo que significa mover una distancia igual (Z o X) al mismo punto M (distancia Z desde P y X desde S) será el inicio del ciclo. ¡Sencillo!
fuente
Con todo el análisis anterior, si usted es una persona que aprende con el ejemplo, traté de escribir un breve análisis y un ejemplo que ayude a explicar las matemáticas que todos los demás intentaron explicar. ¡Aquí vamos!
Análisis:
Si tenemos dos punteros, uno más rápido que el otro, y los movemos juntos, eventualmente se encontrarán nuevamente para indicar un ciclo o nulos para indicar que no hay ciclo.
Para encontrar el punto de partida del ciclo, dejemos ...
m
ser la distancia desde la cabeza hasta el comienzo del ciclo;d
ser el número de nodos en el ciclo;p1
ser la velocidad del puntero más lento;p2
ser la velocidad del puntero más rápido, por ejemplo. 2 significa pasos a través de dos nodos a la vez.Observe las siguientes iteraciones:
A partir de los datos de muestra anteriores, podemos descubrir fácilmente que cada vez que se encuentran los punteros más rápidos y más lentos, están a unos
m
pasos del comienzo del ciclo. Para resolver esto, vuelva a colocar el puntero más rápido en la cabeza y ajuste su velocidad a la velocidad del puntero más lento. Cuando se vuelven a encontrar, el nodo es el comienzo del ciclo.fuente
digamos,
Tenemos 2 punteros A y B, A corre a velocidad 1x, B a velocidad 2x, ambos comienzan desde el principio.
cuando A alcanza N [0], B ya debería estar en N [m]. (Nota: A usa m pasos para alcanzar N [0], y B debe estar m pasos más adelante)
Luego, A ejecuta k más pasos para colisionar con B, es decir, A está en N [k], B está en N [m + 2k] (Nota: B debe ejecutar 2k pasos a partir de N [m])
A colisionan B en N [k] y N [m + 2k] respectivamente, significa k = m + 2k, por lo tanto k = -m
Por lo tanto, para volver al N [0] desde N [k], necesitamos m más pasos.
Simplemente diciendo, solo necesitamos ejecutar m pasos más después de encontrar el nodo de colisión. Podemos tener un puntero para ejecutar desde el principio y un puntero desde el nodo de colisión, se encontrarán en N [0] después de m pasos.
Por lo tanto, los pseudocódigos son los siguientes:
fuente
No creo que sea cierto que cuando se encuentran ese es el punto de partida. Pero sí, si el otro puntero (F) estaba en el punto de encuentro antes, entonces ese puntero estará al final del bucle en lugar del inicio del bucle y el puntero (S) que comenzó desde el principio de la lista lo hará terminar al comienzo del ciclo. por ejemplo:
fuente
Una explicación simple que utiliza la idea de la velocidad relativa que se enseña en la escuela secundaria: conferencias de física 101 / cinemática.
Supongamos que la distancia desde el inicio de la lista vinculada hasta el inicio del círculo es
x
saltos. Llamemos al inicio del círculo como puntoX
(en mayúsculas; consulte la figura anterior). También supongamos que el tamaño total del círculo es N saltos.Velocidad de liebre = 2 * Velocidad de tortuga. Entonces eso es
1 hops/sec
y2 hops/sec
respectivamenteCuando la tortuga alcanza el comienzo del círculo
X
, la liebre debe estar másx
lejos en el puntoY
de la figura. (Porque la liebre ha recorrido el doble de distancia que la tortuga).Por lo tanto, la longitud del arco restante en el sentido de las agujas del reloj de X a Y sería
N-x
. Esto también es la distancia relativa a cubrir entre la liebre y la tortuga para que puedan encontrarse . Digamos que esta distancia relativa se cubrirá en el tiempo,t_m
es decir, el tiempo para encontrarse. La velocidad relativa es(2 hops/sec - 1 hops/sec)
ie1 hops/sec
. Así, usando, distancia relativa = velocidad relativa X tiempo, obtenemos,t
=N-x
seg. Por lo tanto, se necesitaráN-x
llegar al punto de encuentro tanto para la tortuga como para la liebre.Ahora en
N-x
segundos y a gran1 hops/sec
velocidad, la tortuga que estaba antes en el puntoX
cubrirá los saltos de Nx para llegar al punto de encuentroM
. Entonces, eso significa que el punto de encuentroM
está en elN-x
lúpulo en sentido antihorario desdeX
= (lo que implica además) => que hay unax
distancia restante desde el puntoM
hacia laX
derecha.Pero
x
también es la distancia para llegar al puntoX
desde el inicio de la lista vinculada.Ahora, no nos importa a qué número de saltos
x
corresponde. Si colocamos una tortuga al comienzo de LinkedList y una tortuga en el punto de encuentroM
y les dejamos saltar / caminar, entonces se encontrarán en el puntoX
, que es el punto (o nodo) que necesitamos.fuente
Trabajar esto con un diagrama ayudaría. Estoy tratando de explicar el problema sin ecuaciones.
fuente
-hay k pasos antes del bucle. No sabemos qué es k y no necesitamos averiguarlo. Podemos trabajar de manera abstracta con solo k.
--Después de k pasos
----- T está al comienzo del ciclo
----- H son k pasos en el ciclo (pasó 2k en total y por lo tanto k en bucle)
** ahora son de tamaño de bucle, separados por k
(tenga en cuenta que k == K == mod (loopsize, k) --eg si un nodo tiene 2 pasos en un ciclo de 5 nodos, también tiene 7, 12 o 392 pasos, entonces, ¿qué tan grande es el ciclo wrt k no? factor en.
Dado que se alcanzan el uno al otro a razón de 1 paso por unidad de tiempo porque uno se mueve dos veces más rápido que el otro, se encontrarán a loopsize - k.
Esto significa que tomará k nodos para alcanzar el comienzo del ciclo y, por lo tanto, la distancia desde la cabeza hasta el inicio del ciclo y la colisión al inicio del ciclo son las mismas.
Así que ahora, después de la primera colisión, mueve T de nuevo a la cabeza. T y H se encontrarán al inicio del ciclo si te mueves a una velocidad de 1 cada uno. (en k pasos para ambos)
Esto significa que el algoritmo es:
// tenga cuidado con el caso cuando k = 0 o T y H se encuentran en la parte superior del bucle calculando la longitud del bucle
- cuente la duración del ciclo moviendo T o H a su alrededor con un contador
- mueva un puntero T2 al encabezado de la lista
- mover la longitud del puntero de los pasos del ciclo
- mueva otro puntero H2 a la cabeza
- mueva T2 y H2 en tándem hasta que se encuentren al inicio del ciclo
¡Eso es!
fuente
Ya hay muchas respuestas a esto, pero una vez se me ocurrió un diagrama para esto que es más intuitivo para mí. Quizás pueda ayudar a otras personas.
Los principales momentos aha para mí fueron:
Dividir T (tortuga) en T1 (pre-loop) y T2 (in-loop).
Resta T de H , donde se superponen visualmente. Lo que queda ( H - T = h' ) es igual a T .
fuente
Sé que ya hay una respuesta aceptada para este problema, pero aún intentaré responder de manera fluida. Asumir:
Ahora, que la liebre y la tortuga se encuentren después del tiempo 't' desde el principio.
Observaciones:
Si, Distancia recorrida por la tortuga = v * t = x + (bk) (decir)
Entonces, Distancia recorrida por la liebre = 2 * v * t = x + (b - k) + b (ya que la liebre ya ha atravesado la parte en bucle)
Ahora, los horarios de las reuniones son los mismos.
=> x + 2 * b - k = 2 * (x + b - k)
=> x = k
Por supuesto, esto significa que la longitud de la ruta que no está en bucle es la misma que la distancia del punto de inicio del bucle desde el punto donde ambos se encuentran.
fuente
En realidad, es fácil demostrar que ambos se encontrarán en el punto de partida, si considera las matemáticas detrás del punto de encuentro.
Primero, denote m el punto de inicio del ciclo en la lista vinculada, yn denota la duración del ciclo. Luego, para que la liebre y la tortuga se encuentren, tenemos:
Dicho esto más matemáticamente:
entonces se encontrarán en el tiempo t, que debería ser un múltiplo de la duración del ciclo. Esto significa que se encuentran en un lugar, que es
(t-m) modulo n = (0-m) modulo n = (-m) modulo n
.Entonces, volviendo a la pregunta, si mueve un puntero desde el inicio de la lista vinculada y otro desde el punto de intersección, después de m pasos, la liebre (que se mueve dentro del ciclo) llegará a un punto que es
((-m) + m) modulo n = 0 modulo n
que no es más que el punto de partida del ciclo. Entonces podemos ver que después de m pasos llega al comienzo del ciclo y la tortuga lo encontrará allí, ya que atravesará m pasos desde el comienzo de la lista vinculada.Como nota al margen, también podemos calcular el tiempo de su intersección de esta manera: la condición
t = 0 modulo n
nos dice que se encontrarán en un momento que es un múltiplo de la duración del ciclo, y también t debería ser mayor que m como se encontrarían en el ciclo . Por lo tanto, el tiempo necesario será igual al primer múltiplo de n, que es mayor que m .fuente
Suponga que sus punteros se encuentran en la intersección de los puntos y y z.
nym son los números de bucles que toma el puntero más rápido y más lento, respectivamente, antes de reunirse.
Consulte la imagen para el resto de la prueba. Encuentre el punto de inicio del bucle en la lista vinculada
fuente