Remove Nth Node From End of List
Put a dummy node before the head. Start slow and fast on the dummy and move fast ahead by n + 1 nodes. Now move both one step at a time. The gap never changes, so when fast becomes null, slow is n + 1 nodes before null, which is the node just before the n-th from the end. Unlink with slow->next = slow->next->next and return dummy.next.
The gap from slow to fast is always exactly n + 1 nodes, so when fast is null, slow is the node just before the n-th node from the end.
Problem
You are given the head of a singly linked list and a number n.
Delete the node that is n-th from the end of the list (the last node is 1st from the end), and return the head of the changed list.
Follow-up: can you do it in one pass over the list?
The head of a linked list, and an integer n with 1 ≤ n ≤ the length of the list.
The head of the list after that one node is removed. It may be a different node than before, or null if the list becomes empty.
Counting from the end: 5 is 1st, 4 is 2nd. So node 4 is removed.
The only node is removed, so the list is empty.
The last node (2) is removed.
- • The list has `sz` nodes, 1 ≤ sz ≤ 30
- • 0 ≤ Node.val ≤ 100
- • 1 ≤ n ≤ sz
First, think yourself
Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.
- 1.
To delete a node in a singly linked list, which node do I actually need to be standing on?
- 2.
What is the n-th node from the end if I count from the front instead? What do I need to know for that?
- 3.
What happens if the node to delete is the head? Is there a node before it?
- 4.
If two pointers are exactly k nodes apart and the front one reaches the end, where is the back one?
- 5.
How far apart should they be so the back one stops one node before the target, not on it?
Brute force approach
Optimized approach
Why does this algorithm work?
Dry run
All approaches compared
| Approach | Idea | Time | Space |
|---|---|---|---|
| Brute Force | Pass 1 counts L; pass 2 stops before index L − n and unlinks it | O(L) | O(1) |
| Optimal | Put fast n + 1 ahead of slow; when fast hits null, slow is just before the target | O(L) | O(1) |
Why does this belong to this pattern?
- “n-th from the end”A position measured from null. A fixed gap between two pointers measures it in one pass.
- “remove a node”You need the node before it, so make the gap one bigger (n + 1).
- “may remove the head”Use a dummy node so the head also has a node before it.
- “one pass”No counting pass first. Let fast do the measuring.
This is the anchor of the gap idea. In cycle and middle problems, fast moves faster than slow. Here both move at the same speed, and fast just starts earlier. The head start (n + 1) is chosen so that when fast reaches the end, slow is exactly where we need it. The next two questions reuse this: Intersection uses a head start equal to the length difference, and Swapping Nodes uses a gap of k − 1 to find the k-th from the end.
Don't make this mistake
When n equals the length, the node to remove is the head and there is no node before it. Without a dummy, fast becomes null after the head start and fast->next crashes. With a dummy, the dummy is the node before the head and the same code works.
With a gap of n, slow lands on the n-th node from the end, not before it. Then slow->next = slow->next->next deletes the node after the target. On [1, 2, 3, 4, 5], n = 2 you'd remove 5 instead of 4.
If the head was removed, head still points at the removed node. dummy.next always points at the real first node of the new list.
This is the pattern-confusion trap: in cycle and middle questions fast moves 2 steps per turn. Here the speed is the same (1 and 1); only the start differs. If fast moved 2 steps, the gap would keep growing and slow would stop near the middle, not near the end.
Want to implement this?
Write it yourself on LeetCode, then come back and compare your code with the solutions above.
Open coding workspaceHow this concept connects to System Design & C++ Systems
Top engineering interviews test whether you understand how algorithms like Linked List — Fast & Slow translate into production architectures and low-level memory mechanics.
Foundations: Object-Oriented Principles in C++23
Class invariants, pure virtual interfaces, and RAII smart pointers.
Food Delivery System (Zomato Architecture)
Real-world machine coding application of algorithms and design patterns.
Pointers vs References Deep Dive
Pointer arithmetic and memory layout under the hood.
Virtual Method Table (vtable) & Memory Layout
Polymorphism, vptr overhead, and multiple inheritance in memory.