Nueva York | LeetCode142 Lista enlazada Ciclo II

LeetCode142 Lista enlazada Ciclo II


Autor: Stefan Su
Hora de creación: 2022-10-29 02:40:13
Ubicación: Ciudad de Nueva York, NY, EE. UU.

DescripciónMedium

Dado el headde una lista enlazada, devuelve el nodo donde comienza el ciclo . Si no hay ciclo, devuelve null.

Hay un ciclo en una lista enlazada si hay algún nodo en la lista al que se puede acceder de nuevo siguiendo continuamente el nextpuntero. Internamente, posse usa para denotar el índice del nodo al que nextestá conectado el puntero de la cola ( 0-indexado ). Es -1si no hay ciclo. Tenga en cuenta que pos no se pasa como parámetro .

No modifique la lista enlazada.

Ejemplo 1

inserte la descripción de la imagen aquí

Input: head = [3,2,0,-4], pos = 1
Output: tail connects to node index 1
Explanation: There is a cycle in the linked list, where tail connects to the second node.
Ejemplo 2

inserte la descripción de la imagen aquí

Input: head = [1,2], pos = 0
Output: tail connects to node index 0
Explanation: There is a cycle in the linked list, where tail connects to the first node.
Ejemplo 3

inserte la descripción de la imagen aquí

Input: head = [1], pos = -1
Output: no cycle
Explanation: There is no cycle in the linked list.
Restricciones
  • El número de nodos en la lista está en el rango [0, 104] .
  • -105 <= Node.val <= 105
  • poses -1o un índice válido en la lista enlazada.

Análisis

Dos puntos

  1. Comprobar si una lista enlazada es cíclica
  2. Si hay un anillo, cómo encontrar la entrada a este anillo

Detalles

  1. Comprobar si una lista enlazada es cíclica

    Puede utilizar el método de dos punteros para definir los punteros fasty slowrespectivamente. A partir del headnodo, el fastpuntero mueve dos nodos a la vez y el slowpuntero mueve un nodo a la vez. Si los punteros fasty slowse encuentran en el camino, significa que la lista enlazada tiene un anillo.

    ¿Por qué fastir a dos nodos e slowir a un nodo, y si hay un anillo, definitivamente se encontrarán en el anillo en lugar de estar escalonados para siempre?

    En primer lugar, el primer punto: el fastpuntero debe entrar primero en el anillo. Si el fastpuntero y el slowpuntero se encuentran, deben encontrarse en el ring, lo cual está fuera de toda duda .

    Entonces, veamos, ¿ por qué el fastpuntero y el slowpuntero deben encontrarse?

    Puede dibujar un anillo y dejar que el fastpuntero comience a alcanzar al slowpuntero en cualquier nodo.
    fasty slowcada uno da un paso más, fasty slowse encuentra

    Esto se debe a fastque da dos pasos y slowda un paso. De hecho, en comparación con slow, fastes un nodo que está cerca de slow, por lo que fastdebe poder superponerse con slow.

  2. Si hay un anillo, cómo encontrar la entrada a este anillo

    En este punto, se puede juzgar si la lista enlazada tiene un anillo, por lo que el siguiente paso es encontrar la entrada de este anillo.

    Suponga que el número de nodos desde el nodo principal hasta el nodo de entrada al anillo es x. El número de nodos desde el nodo de entrada del anillo hasta el nodo donde el fastpuntero se encuentra con el slowpuntero es y. El número de nodos desde el nodo de encuentro hasta el nodo de entrada al anillo es z. Como muestra la imagen:

    inserte la descripción de la imagen aquí

    Luego, cuando se encuentran: El número de nodos pasados ​​por el slowpuntero es: x + y, el número de nodos pasados ​​por el fastpuntero: x + y + n (y + z), donde nestá el fastpuntero después de nlos círculos en el anillo para encontrarse con el slowpuntero, (y+z)es el número A de nodos en un círculo.

    Debido a que el fastpuntero recorre dos nodos a la vez, y el slowpuntero recorre un nodo a la vez, el número de nodos atravesados ​​por el fastpuntero es igual al doble del número de nodos atravesados ​​por el slowpuntero:

    (x + y) * 2 = x + y + n(y + z)

    Eliminar uno en ambos lados (x+y):x + y = n (y + z)

    Debido a que se debe encontrar la entrada al anillo, xes obligatorio, porque xrepresenta la distancia desde el nodo principal hasta el nodo de entrada al anillo.

    Así que pide que xse ponga xsolo a la izquierda x = n (y + z) - y:

    Entonces crea un (y+z)from n(y+z). Después de resolver la fórmula, es la siguiente fórmula: x = (n - 1) (y + z) + zTenga en cuenta que n debe ser mayor o igual que 1 aquí, porque el fastpuntero debe recorrer al menos un círculo más para encontrarse con el slowpuntero.

    ¿Qué dice esta fórmula?

    Tomemos el caso en el que n es 1 como ejemplo, lo que significa que después de que el puntero rápido da la vuelta en el anillo, se encuentra con el puntero lento.

    Cuando n es 1, la fórmula se resuelve en x = z,

    Esto significa que se establece un puntero desde el nodo principal y también se establece un puntero desde el nodo de encuentro. Estos dos punteros solo van un nodo a la vez, por lo que cuando estos dos punteros se encuentran, es el nodo de la entrada del anillo .

    Es decir, en el nodo de encuentro, defina un puntero index1y establezca un puntero index2en el nodo principal.

    Deje index1y index2se mueva al mismo tiempo, un nodo a la vez, luego el lugar donde se encuentran es el nodo de la entrada del anillo.

    Entonces, ¿qué sucede si n es mayor que 1, es decir, el fastpuntero se encuentra con el slowpuntero después de n círculos en el anillo?

    De hecho, esta situación es la misma que cuando n es 1, y el nodo de entrada del anillo se puede encontrar con este método, pero el index1puntero gira (n-1)más veces en el anillo y luego se encuentra index2, el punto de encuentro sigue siendo el nodo de entrada. del anillo

Solución

  • Versión de dos punteros
/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    
    
    public ListNode detectCycle(ListNode head) {
    
    
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
    
    
            fast = fast.next.next;
            slow = slow.next;

            if (slow == fast) {
    
    
                ListNode index_1 = fast;
                ListNode index_2 = head;
                while (index_1 != index_2) {
    
    
                    index_1 = index_1.next;
                    index_2 = index_2.next;
                }
                return index_1;
            }
        }
        return null;
    }
}

Con suerte, este blog puede inspirarte a la hora de resolver LeetCode142. Para cualquier pregunta, por favor comente a continuación.

Supongo que te gusta

Origin blog.csdn.net/Moses_SU/article/details/127586364
Recomendado
Clasificación