DDSA Solutions

19. Remove Nth Node From End of List

Time: O(n)
Space: O(1)

Problem Overview

To find the nth node from the end without knowing the list length, use a two-pointer gap trick: if fast is exactly n steps ahead of slow, then when fast reaches the tail, slow is precisely at the node we want to remove.

Advertisement

Intuition

To find the nth node from the end without knowing the list length, use a two-pointer gap trick: if fast is exactly n steps ahead of slow, then when fast reaches the tail, slow is precisely at the node we want to remove. A dummy node before head lets us handle removing the head itself cleanly.

Algorithm

  1. 1Create a dummy node pointing to head; initialise both fast and slow at dummy.
  2. 2Advance fast n+1 steps forward (so the gap between slow and fast is n+1).
  3. 3Move both fast and slow one step at a time until fast == null.
  4. 4Now slow.next is the node to delete. Set slow.next = slow.next.next.
  5. 5Return dummy.next.

Example Walkthrough

Input: head = [1->2->3->4->5], n = 2

  1. 1.dummy->1->2->3->4->5. Advance fast 3 steps: fast=3, slow=dummy.
  2. 2.Move both: fast=4, slow=1. Move both: fast=5, slow=2. Move both: fast=null, slow=3.
  3. 3.slow.next (node 4) is the 2nd from end. slow.next = node 5.
  4. 4.List becomes 1->2->3->5.

Output: [1, 2, 3, 5]

Common Pitfalls

  • Advance fast n+1 (not n) steps so slow stops one node BEFORE the target.
  • The dummy node is essential: without it, removing the head (n == list length) requires a special case.
19.cs
C#
// Approach: Use a dummy node before head to cleanly handle the edge case of removing the head itself.
// Advance the fast pointer n+1 steps ahead of slow (both starting at dummy).
// Move both pointers one step at a time until fast reaches null.
// At that point slow.next is the node to delete; redirect slow.next = slow.next.next.
// Single pass — no need to know the list length or make a second traversal.
// Time: O(n) Space: O(1)

public class ListNode
{
    public int val;
    public ListNode next;
    public ListNode(int val = 0, ListNode next = null)
    {
        this.val = val;
        this.next = next;
    }
}

public class Solution
{
    public ListNode RemoveNthFromEnd(ListNode head, int n)
    {
        ListNode start = new ListNode();
        start.next = head;
        ListNode slow = start;
        ListNode fast = start;
        for (int i = 1; i <= n; i++)
        {
            fast = fast.next;
        }

        while (fast.next != null)
        {
            fast = fast.next;
            slow = slow.next;
        }

        slow.next = slow.next.next;
        return start.next;
    }
}
Advertisement
Was this solution helpful?

Related Problems