#19 - Remove Nth Node From End of List
Given the head of a linked list, remove the n-th node from the end of the list and return its head.
| Input | Output |
|---|---|
head = [1,2,3,4,5], n = 2 | [1,2,3,5] |
head = [1], n = 1 | [] |
head = [1,2], n = 1 | [1] |
Given the head of a linked list, remove the n-th node from the end of the list and return its head.
| Input | Output |
|---|---|
head = [1,2,3,4,5], n = 2 | [1,2,3,5] |
head = [1], n = 1 | [] |
head = [1,2], n = 1 | [1] |
/**
* Removes the n-th node from the end of the list in one pass.
* Uses a dummy node to simplify edge cases (e.g. removing the head).
*
* @param head Head of the linked list
* @param n 1-based position from the end to remove
* @returns Head of the modified list
*/
export function removeNthFromEnd(
head: ListNode | null,
n: number,
): ListNode | null {
const dummy = new ListNode(0, head);
let first: ListNode | null = dummy;
let second: ListNode | null = dummy;
// Advance first pointer n + 1 steps so the gap is n nodes
for (let i = 0; i <= n; i++) {
first = first!.next;
}
// Move both until first reaches the end
while (first) {
first = first.next;
second = second!.next;
}
// second is now right before the target node — skip it
second!.next = second!.next!.next;
return dummy.next;
}
Approach: two-pointer gap technique – create a gap of `n` nodes between `first` and `second`. When `first` reaches the end, `second` sits right before the node to remove. A dummy node before `head` handles the edge case of removing the head itself.
Time: O(L) where L is the list length – single pass.
Space: O(1) – only pointer variables and one dummy node.