Last Updated: March 29, 2026
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.
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.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.
head. This handles the edge case where we need to remove the head.length).length - n steps from the dummy.prev.next = prev.next.next to skip the target node.dummy.next (which is the new head).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?
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.
Think of it like a ruler. If you have a ruler that's n units long and you slide it along the list until the right end falls off, the left end marks where you need to be. The gap between the two pointers is always n, so when the fast pointer hits null, the slow pointer is (n+1) nodes from the end, which is exactly the predecessor of the node we want to delete.
Using a dummy node before the head means the slow pointer starts one position earlier, which naturally lands it on the predecessor of the target.
Always mention the dummy node trick when working with linked list problems. It shows you know how to avoid messy edge cases for head deletion. Many candidates waste time with special-case if statements that a dummy node eliminates entirely.
head.fast and slow at the dummy node.fast by n + 1 steps. Now fast is n + 1 nodes ahead of slow.fast and slow one step at a time until fast reaches null.slow is the node just before the target. Set slow.next = slow.next.next.dummy.next.Walk through this example on the whiteboard during your interview. Interviewers love seeing candidates trace through pointer movements step by step. It demonstrates that you truly understand the algorithm, not just memorized code.
If the interviewer asks "Can you do this in one pass?", this is the answer. The two-pointer technique eliminates the counting pass entirely. Mention that the total pointer movements are the same (still O(n)), but we only traverse the list once, which matters in streaming or disk-based scenarios where re-reading data is expensive.