Remove the Nth Node from the End

This one looks small. But it traps a lot of people. The interviewer hands you a linked list and says β€œdelete the nth node, but count from the end.” So now you have a problem. In a singly linked list you can only walk forward. You cannot jump to the end and count backward. So how do you find a node from the back when you can only move from the front? That is the real thing being tested here. Can you turn β€œfrom the end” into β€œfrom the front” without walking the list twice?

πŸ”— The Problem

You are given the head of a singly linked list and a number n. You have to remove the node that is the nth one counting from the end. Then return the head of the changed list.

Here n counts from the back. So n = 1 means the last node. And n = 2 means the second-to-last node. And so on.

Input: 1 -> 2 -> 3 -> 4 -> 5, n = 2
Output: 1 -> 2 -> 3 -> 5
We removed node 4, because 4 is the 2nd node from the end.

To delete a node in a singly linked list, you do not touch the node itself. You change the next pointer of the node before it. So the real job is to stop at the node just before the one you want to remove.

🐒 The Simple Approach: Count First, Then Delete

The first idea that comes to mind is simple. Walk the whole list once and count how many nodes there are. Say the length is L. The nth node from the end is the (L - n)th node from the front. So now you walk again from the front and stop right before it. Then you fix the pointer.

This works fine. It gives the right answer. But see, you walked the list two times. Once to count. Once to delete. The interviewer will almost always smile and ask, β€œCan you do it in one pass?” That is the hint that they want something better.

πŸ‡ The Optimal Approach: Two Pointers with a Gap

Here is the trick. We use two pointers. And we keep a fixed gap between them.

Think of two people walking on the same road. Riya starts first. She walks n steps ahead. Then Arjun starts from the beginning. Now both walk at the same speed, one step at a time. The gap between them stays exactly n the whole time. So when Riya reaches the very end, Arjun is sitting exactly n nodes behind the end. That is exactly the spot we care about.

We want to stop Arjun just before the node to delete. So we make the gap a little bigger and start Arjun from a fake node. This fake node is called a dummy head. It is an extra node we place before the real head. Why do we need it? Because what if you have to delete the first node itself? Then there is no node before it. The dummy head gives us a safe node to stand on. So the same code works even for the head.

Here n is assumed to be valid. That means it is between 1 and the length of the list.

Steps to do it in one pass:

  1. Create a dummy node and point its next to the head. Set both fast and slow to this dummy node.
  2. Move fast forward by n steps. Now there is a gap of n between fast and slow.
  3. Move both fast and slow one step at a time until fast reaches the last node (its next is null).
  4. Now slow is sitting right before the node to remove. Set slow.next = slow.next.next to skip over it.
  5. Return dummy.next as the new head.
remove_nth_from_end.py
class Node:
def __init__(self, value):
self.data = value
self.next = None
# Remove the nth node from the end in one pass
def remove_nth_from_end(head, n):
dummy = Node(0) # dummy head
dummy.next = head
fast = dummy
slow = dummy
# Move fast n steps ahead so the gap becomes n
for _ in range(n):
fast = fast.next
# Move both until fast is at the last node
while fast.next is not None:
fast = fast.next
slow = slow.next
# slow is right before the target; skip the target
slow.next = slow.next.next
return dummy.next
def print_list(head):
parts = []
while head is not None:
parts.append(str(head.data))
head = head.next
print(" -> ".join(parts))
# Build 1 -> 2 -> 3 -> 4 -> 5
head = Node(1)
head.next = Node(2)
head.next.next = Node(3)
head.next.next.next = Node(4)
head.next.next.next.next = Node(5)
head = remove_nth_from_end(head, 2)
print_list(head)

The output of the above code will be:

1 -> 2 -> 3 -> 5

⏱️ Time and Space Complexity

Both approaches walk a constant number of times. So both are O(n) in time. The real difference is the number of passes. The two-pointer way does it in a single pass. That is the version the interviewer wants to see.

Approach Passes Time Space
Count first, then delete Two O(n) O(1)
Two pointers with a gap One O(n) O(1)

Tip

The dummy head is the part people forget. Without it, deleting the first node crashes, because slow has no node to stand on before the head. When the interviewer gives an edge case like β€œthe list has one node and n = 1”, the dummy head makes your code just work. Mention it out loud and you score points.

🧩 Key Takeaways

  • βœ… β€œNth from the end” becomes β€œnth from the front” once you keep a fixed gap of n between two pointers.
  • βœ… Move the fast pointer n steps ahead first. Then move both together until fast hits the last node.
  • βœ… A dummy head before the real head lets the same code delete the first node safely.
  • βœ… You delete a node by changing the next of the node before it. So always stop at the node before the target.
  • βœ… This runs in one pass: O(n) time and O(1) extra space.

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    Why do we use a dummy node before the head?

    Why: The dummy gives slow a node to stand on before the head, so removing the first node needs no special case.

  2. 2

    After moving fast n steps ahead, what is true when fast reaches the last node?

    Why: The gap of n stays fixed, so when fast is at the end, slow sits just before the target node.

  3. 3

    How do you actually remove the target node in a singly linked list?

    Why: You change the previous node's next pointer so it points past the target, skipping it.

  4. 4

    What is the time and space complexity of the two-pointer solution?

    Why: It does a single pass over the list and uses only a couple of pointers.

πŸš€ What’s Next?

Share & Connect