AlgoMaster Logo

Remove Nth Node From End of List

Last Updated: March 29, 2026

medium
3 min read

Understanding the Problem

We need to remove the nth node from the end of a singly linked list. If the list has 5 nodes and n = 2, we remove the 4th node (0-indexed: position 3), which is the second from the end.

The challenge with singly linked lists is that we can't traverse backward. So "nth from the end" isn't as simple as indexing from the back. We need to figure out which node that is by traversing forward. And to actually remove a node, we need a pointer to the node before it so we can rewire the next pointer.

There's also a tricky edge case: when n equals the length of the list, we're removing the head itself. This requires special handling since there's no node before the head, unless we use a dummy node trick.

Key Constraints:

  • 1 <= sz <= 30 -> The list is small, so even O(n^2) would be fine. But this problem is really about technique, not performance. The interviewer wants to see clean pointer manipulation.
  • 1 <= n <= sz -> n is always valid. We don't need to handle cases where n is larger than the list size. This simplifies our logic.
  • 0 <= Node.val <= 100 -> Node values are non-negative. Not relevant to our algorithm, but good to note.

Approach 1: Two Pass (Count then Remove)

Intuition

The most natural approach: if we know the total length of the list, then the nth node from the end is the (length - n + 1)th node from the start (1-indexed). So we can make one pass to count all nodes, then a second pass to find the node just before the target and rewire pointers.

This is clean and easy to implement. The only subtlety is when we need to remove the head node itself (when n equals the list length), since there's no node before the head. A dummy node eliminates this edge case entirely.

Algorithm

  1. Create a dummy node that points to head. This handles the edge case where we need to remove the head.
  2. First pass: traverse the entire list to count the total number of nodes (length).
  3. Calculate the position of the node just before the target: we need to advance length - n steps from the dummy.
  4. Second pass: traverse to that position, then set prev.next = prev.next.next to skip the target node.
  5. Return dummy.next (which is the new head).

Example Walkthrough

1Initial list: [1, 2, 3, 4, 5], n = 2
1
2
3
4
5
null
1/6

Code

This approach works correctly but requires two traversals.

What if we could figure out where the nth-from-end node is without knowing the total length? Could two pointers spaced n apart help us find the right position in a single pass?

Approach 2: One Pass (Two Pointers)

Intuition

Here's the key insight: if we place two pointers n nodes apart and then advance both at the same speed, when the lead pointer reaches the end, the trailing pointer will be exactly at the node before the one we want to remove.

Algorithm

  1. Create a dummy node pointing to head.
  2. Initialize both fast and slow at the dummy node.
  3. Advance fast by n + 1 steps. Now fast is n + 1 nodes ahead of slow.
  4. Move both fast and slow one step at a time until fast reaches null.
  5. Now slow is the node just before the target. Set slow.next = slow.next.next.
  6. Return dummy.next.

Example Walkthrough

1Initialize: slow = dummy, fast = dummy. List: [1, 2, 3, 4, 5], n = 2
1
2
3
4
5
null
1/9

Code