19. Eliminar el enésimo nodo del final de la lista
Dado el encabezado de una lista vinculada, elimine nthn^{th}nortet h nodo del final de la lista y devuelve su encabezado.
Ejemplo 1:
Entrada: cabeza = [1,2,3,4,5], n = 2
Salida: [1,2,3,5]
Ejemplo 2:
Entrada: cabeza = [1], n = 1
Salida: []
Ejemplo 3:
Entrada: cabeza = [1,2], n = 1
Salida: [1]
Restricciones:
- El número de nodos en la lista es sz.
- 1 <= tamaño <= 30
- 0 <= Valor.nodo <= 100
- 1 <= n <= tamaño
De: Enlace LeetCode : 19. Eliminar el enésimo nodo del final de la lista
Solución:
Ideas:
Conceptos clave:
- Técnica de dos punteros: utilizamos dos punteros que inicialmente apuntan al encabezado de la lista.
- Nodo ficticio: un nodo ficticio se utiliza para manejar casos extremos más fácilmente, como cuando es necesario eliminar el nodo principal.
Algoritmo:
-
Crear un nodo ficticio: se crea un nodo ficticio y se configura para que apunte al encabezado de la lista. Esto simplifica el código para casos extremos.
-
Inicializar dos punteros: tanto el primer como el segundo puntero se inicializan para apuntar al nodo ficticio.
-
Avanzar el primer puntero: el primer puntero avanza n+1 pasos desde el principio. Esto crea una brecha de n nodos entre el primero y el segundo.
-
Mover ambos punteros: tanto el primer como el segundo puntero se mueven paso a paso hasta que el primero llega al final de la lista. La brecha de n nodos se mantiene entre el primero y el segundo.
-
Eliminar nodo: en este punto, el segundo apuntará al nodo inmediatamente anterior al nodo que debe eliminarse. Eliminamos el enésimo nodo del final.
-
Devolver nuevo encabezado: el nuevo encabezado de la lista se devuelve después de liberar el nodo ficticio.
Código:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
struct ListNode *dummy = malloc(sizeof(struct ListNode));
dummy->val = 0;
dummy->next = head;
struct ListNode *first = dummy;
struct ListNode *second = dummy;
// Advance first pointer by n+1 steps from the beginning,
// so the gap between first and second is n nodes apart
for (int i = 1; i <= n + 1; i++) {
first = first->next;
}
// Move first to the end, maintaining the gap
while (first != NULL) {
first = first->next;
second = second->next;
}
// Remove the n-th node from the end
struct ListNode *temp = second->next;
second->next = second->next->next;
free(temp);
// Return new head node
struct ListNode *newHead = dummy->next;
free(dummy);
return newHead;
}