19. Remove Nth Node From End of List
Given the head of a linked list, remove the n t h n^{th} nth node from the end of the list and return its head.
Example 1:
Input: head = [1,2,3,4,5], n = 2
Output: [1,2,3,5]
Example 2:
Input: head = [1], n = 1
Output: []
Example 3:
Input: head = [1,2], n = 1
Output: [1]
Constraints:
- The number of nodes in the list is sz.
- 1 <= sz <= 30
- 0 <= Node.val <= 100
- 1 <= n <= sz
From: LeetCode
Link: 19. Remove Nth Node From End of List
Solution:
Ideas:
Key Concepts:
- Two-Pointer Technique: We use two pointers that initially point to the head of the list.
- Dummy Node: A dummy node is used to handle edge cases more easily, like when the head node itself needs to be removed.
Algorithm:
-
Create a Dummy Node: A dummy node is created and set to point to the head of the list. This simplifies the code for edge cases.
-
Initialize Two Pointers: Both first and second pointers are initialized to point to the dummy node.
-
Advance the First Pointer: The first pointer is advanced n+1 steps from the beginning. This creates a gap of n nodes between first and second.
-
Move Both Pointers: Both first and second pointers are moved one step at a time until first reaches the end of the list. The gap of n nodes is maintained between first and second.
-
Remove Node: At this point, second will be pointing to the node immediately before the node that needs to be removed. We remove the n-th node from the end.
-
Return New Head: The new head of the list is returned after freeing the dummy node.
Code:
c
/**
* 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;
}