Remove Nth Node From End of List
๐ฏ Difficulty: MEDIUM
๐ LeetCodeProblem Statement
Given the head of a linked list, remove the 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]
Approach: Two Pointers with a Dummy Node
To remove a node from a linked list, we need a pointer to the node immediately preceding it. Finding the node from the end in a single pass can be done elegantly using two pointers separated by a specific distance.
Using a Dummy Node at the start of the list is a crucial technique here because it handles edge cases effortlessly (such as when the node to be removed is the very first node in the list).
- Initialize a Dummy Node: Create a
dummynode that points itsnextto theheadof the list. This will be the new anchor. - Setup Two Pointers: Initialize two pointers,
leftandright, both starting at thedummynode. - Create the Gap: Move the
rightpointer forward by exactlyn + 1steps. This establishes a gap ofnnodes betweenleftandright. - Slide the Window: Move both
leftandrightforward one step at a time untilrightreachesnull(the end of the list).- Because of the gap we created, when
righthitsnull, theleftpointer will be positioned exactly on the node just before the target node we want to remove.
- Because of the gap we created, when
- Delete the Target Node: Update the
nextpointer of theleftnode to skip the target node:left.next = left.next.next. - Return the Result: The true head of the modified list is
dummy.next.
Solution
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} n
* @return {ListNode}
*/
function removeNthFromEnd(head, n) {
// 1. Initialize a dummy node to handle edge cases
let dummy = new ListNode(0, head);
let left = dummy;
let right = dummy;
// 2. Move right pointer n + 1 steps ahead
for (let i = 0; i <= n; i++) {
right = right.next;
}
// 3. Move both pointers until right reaches the end
while (right !== null) {
left = left.next;
right = right.next;
}
// 4. Delete the nth node from the end
left.next = left.next.next;
// 5. Return the head of the modified list
return dummy.next;
}
Complexity Analysis
- Time Complexity: where is the length of the linked list. The algorithm makes exactly one traversal of the list, visiting each node at most once.
- Space Complexity: . We only allocate a single
dummynode and two pointers (left,right), resulting in constant extra space.