【LeetCode】 Inversión de lista vinculada

tema

Título: dado el nodo principal de una lista enlazada individualmente, invierta el orden de los enlaces de la lista enlazada individualmente
Ejemplo:
Entrada: 1->2->3->4->5
Salida: 5->4->3->2 ->1
Requisitos: implementado de dos maneras

Solución

Método 1: (método de iteración directa)

tren de pensamiento

La estructura de una lista enlazada individualmente es la siguiente:
inserte la descripción de la imagen aquí
Como se muestra en la figura. Analicemos en qué debemos pensar si queremos completar el giro:

  1. Recorre todos los nodos hasta el final. Entonces necesitas confirmar la condición final.
  2. Apunte de forma segura el nodo actual a su nodo predecesor (apuntar directamente a él hará que falle el recorrido de la lista vinculada, como se muestra a continuación, no se puede encontrar el siguiente nodo de operación)
    inserte la descripción de la imagen aquí

Para el primer punto, dado que desea realizar un bucle, no es más que un iterador o un bucle. Obviamente no hay forma de utilizar un iterador aquí, así que considere usar un bucle while. ¿Cuando terminará? No es difícil encontrar que es [cuando el siguiente nodo del nodo actual es nulo], o agregamos un nuevo nodo currNodepara representar el nodo de operación actual, que se mueve hacia atrás con la profundidad transversal. Obviamente su valor inicial es headel nodo principal, por lo que puede usarse currNode == nullpara indicar el final del recorrido.
Para el punto 2, ¿cómo puede el nodo actual apuntar de forma segura a su nodo predecesor? Normalmente, se requieren los siguientes 2 pasos para garantizar:

  1. Registre el siguiente nodo señalador original del nodo actual, que se registra aquí oldNextNode(consulte la figura anterior para conocer el motivo)
  2. También se necesita un nodo precursor preNodepara registrar el nodo precursor que debe configurarse para el siguiente nodo (también puede ver la figura anterior, excepto que no se puede encontrar el siguiente nodo, de hecho, el siguiente nodo no puede encontrar el nodo anterior. por lo que también es necesario registrarlo)

Cuando estemos listos podemos probar la simulación.
inserte la descripción de la imagen aquí
Pasos:

  1. establecer oldNextNodeen currNodeel siguiente nodo
  2. Señale currNodeel siguiente nodo depreNode
  3. preNodeEstablecer comocurrNode
  4. currNodeConfigurarlo oldNextNode
    inserte la descripción de la imagen aquí
    parece estar bien, así que comencemos a escribir código.

ejemplo de código

El código se muestra a continuación:

public class ReverseLinkedList {
    
    
    public static void main(String[] args) {
    
    
        ListNode node5 = new ListNode(5, null);
        ListNode node4 = new ListNode(4, node5);
        ListNode node3 = new ListNode(3, node4);
        ListNode node2 = new ListNode(2, node3);
        ListNode node1 = new ListNode(1, node2);

        reverseLinkedList(node1);
    }

    private static void reverseLinkedList(ListNode head) {
    
    

        // 初始化我们的中间节点
        ListNode currNode = head;
        ListNode oldNextNode = null;
        ListNode preNode = null;

        // 循环遍历,currNode != null 则表示还没遍历到结尾
        while (currNode != null) {
    
    
            oldNextNode = currNode.next;
            currNode.next = preNode;
            preNode = currNode;
            currNode = oldNextNode;
        }

        System.out.println("试试看");
        System.out.println(preNode);
    }
}

Finalmente, veamos el resultado: ¡
inserte la descripción de la imagen aquí
está al revés!

Método 2: (método recursivo)

tren de pensamiento

(PD: dado que se dice que se resuelve mediante recursividad, primero debemos saber qué puede hacer la recursividad. Se puede decir que cualquier problema que pueda resolverse mediante recursividad debe poder dividir un problema grande en N problemas pequeños con puntos en común pregunta. Entonces, podemos mirar en esa dirección.)

Aún mirando el diagrama de estructura de la lista enlazada individualmente:
inserte la descripción de la imagen aquí
encontramos que si comenzamos desde el último nodo, el problema de este tema se convertirá en otro problema:¿Quién es mi nodo precursor?
En el recorrido normal, utilizamos preNodenodos de estado para realizar un seguimiento de los nodos predecesores, ¡pero en la recursividad es menos complicado! Porque al atravesar nodos de forma recursiva hacia adelante, el final del nodo actual debe estar en el lugar de llamada del nodo predecesor. El diagrama de efectos es el siguiente:
inserte la descripción de la imagen aquí
el código recursivo es el siguiente:

    public static void main(String[] args) {
    
    
        ListNode node5 = new ListNode(5, null);
        ListNode node4 = new ListNode(4, node5);
        ListNode node3 = new ListNode(3, node4);
        ListNode node2 = new ListNode(2, node3);
        ListNode node1 = new ListNode(1, node2);

//        reverseLinkedList(node1);
        recursion(node1);
    }

    private static ListNode recursion(ListNode curr) {
    
    

        // 递归出口(遍历到最后了)
        if (curr == null || curr.next == null) {
    
    
            return curr;
        }

        ListNode recursion = recursion(curr.next);
        System.out.println(recursion.value);
        return curr;
    }
//    系统输出:
//            5
//            4
//            3
//            2

Ahora que conocemos esta característica, solo nos falta realizar los siguientes pasos:

  1. Cada llamada recursiva devuelve el nodo actual (esto es para crear un entorno donde el nodo actual pueda estar en el mismo bloque de código que el nodo predecesor)
  2. Después de obtener el nodo devuelto por la llamada recursiva recursion , recursion .next = curr; curr.next = null;úselo
    inserte la descripción de la imagen aquí

ejemplo de código

   public static void main(String[] args) {
    
    
        ListNode node5 = new ListNode(5, null);
        ListNode node4 = new ListNode(4, node5);
        ListNode node3 = new ListNode(3, node4);
        ListNode node2 = new ListNode(2, node3);
        ListNode node1 = new ListNode(1, node2);

//        reverseLinkedList(node1);
        recursion(node1);
        System.out.println(node5);
    }

    private static ListNode recursion(ListNode curr) {
    
    

        // 递归出口(遍历到最后了)
        if (curr == null || curr.next == null) {
    
    
            return curr;
        }

        ListNode recursion = recursion(curr.next);
        recursion.next = curr;
        curr.next = null;
        return curr;
    }

Finalmente, veamos el resultado:
inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/qq_32681589/article/details/132032647
Recomendado
Clasificación