Remove Nth Node From End Of List

8 min read

Remove Nth Node From End of List: A Complete Guide

If you’ve ever prepared for a technical interview, you’ve likely encountered the classic linked list problem: remove nth node from end of list. But beyond interviews, this problem is a great exercise in writing clean, efficient code. It’s a favorite among interviewers because it tests your understanding of linked list traversal, edge cases, and the subtle art of using two pointers. In this article, we’ll break down the problem step by step, explore two solid approaches, and make sure you walk away with a deep understanding—not just a memorized solution Still holds up..

Understanding the Problem Statement

Before diving into code, let’s clearly define what we’re trying to achieve. You are given a singly linked list and an integer n. Your task is to remove the n-th node from the end of the list and return the head of the modified list.

This changes depending on context. Keep that in mind Simple, but easy to overlook..

Take this: consider the linked list:

1 -> 2 -> 3 -> 4 -> 5

If n = 2, the node to remove is the second from the end, which is 4. The resulting list becomes:

1 -> 2 -> 3 -> 5

Seems simple, right? But there are a few important constraints to keep in mind:

  • The list is singly linked, meaning you can only traverse forward.
  • The value of n is always valid (i.e., it won’t be zero or larger than the number of nodes).
  • You need to handle the case where the node to remove is the head itself.

Now, let’s explore two main approaches to solve this problem: the straightforward two-pass method and the more elegant one-pass two-pointer technique Practical, not theoretical..

Approach 1: The Two-Pass Algorithm

The most intuitive way to solve this problem is to use two passes through the list. On the flip side, then, calculate the position of the target node from the start. The idea is simple: first, find the length of the list. Finally, traverse to the node just before the target and adjust its next pointer.

Not obvious, but once you see it — you'll see it everywhere.

Steps for the Two-Pass Method

  1. Find the length of the linked list by traversing from head to tail. Let’s call this length.
  2. Compute the index of the node to remove from the start: index_to_remove = length - n. This is the zero-based position from the head.
  3. Handle the head removal case: If index_to_remove == 0, the head itself must be removed. Simply return head.next.
  4. Traverse to the node before the target: Move index_to_remove - 1 steps from the head to reach the previous node.
  5. Update the pointer: Set prev.next = prev.next.next to skip the target node.
  6. Return the head of the modified list.

Here’s how this looks in Python:

def removeNthFromEnd(head, n):
    # Step 1: Find the length of the list
    length = 0
    current = head
    while current:
        length += 1
        current = current.next
    
    # Step 2: Compute the index from the start
    index_to_remove = length - n
    
    # Step 3: If removing the head
    if index_to_remove == 0:
        return head.next
    
    # Step 4: Traverse to the node before the target
    prev = head
    for _ in range(index_to_remove - 1):
        prev = prev.next
    
    # Step 5: Skip the target node
    prev.next = prev.next.next
    
    # Step 6: Return the head
    return head

Time and Space Complexity

  • Time complexity: O(L), where L is the length of the list. We traverse the list twice, but each pass is linear, so the total is still O(L).
  • Space complexity: O(1), since we only use a constant amount of extra space (a few pointers).

The two-pass approach is easy to understand and implement, but it does require two full traversals. Can we do better? Yes—by using the two-pointer technique.

Approach 2: One-Pass with Two Pointers

The two-pointer method is more efficient in practice because it only requires a single traversal. The core idea is to maintain a gap of n nodes between two pointers. When the fast pointer reaches the end of the list, the slow pointer will be exactly at the node before the one we want to remove That's the part that actually makes a difference..

Steps for the Two-Pointer Method

  1. Create a dummy node that points to the head. This helps handle edge cases where the head is removed, and it simplifies the code.
  2. Initialize two pointers: fast and slow, both starting at the dummy node.
  3. Move fast ahead by n + 1 nodes. Why n + 1? Because we want slow to point to the node before the target when fast reaches the end. This way, we can easily unlink the target node.
  4. Move both pointers one step at a time until fast becomes None. At this point, slow.next is the node to remove.
  5. Update the pointer: Set slow.next = slow.next.next to skip the target.
  6. Return dummy.next as the new head.

Let’s see the code:

def removeNthFromEnd(head, n):
    dummy = ListNode(0, head)  # dummy node pointing to head
    fast = slow = dummy
    
    # Move fast ahead by n+1 nodes
    for _ in range(n + 1):
        fast = fast.next
    
    # Move both pointers until fast reaches the end
    while fast:
        fast = fast.next
        slow = slow.next
    
    # Skip the target node
    slow.next = slow.next.next
    
    return dummy.next

Why Does This Work?

The key is the fixed gap of n nodes between fast and slow. That's why nextis then-th node from the end. When fastreaches the end (i.e.Worth adding: ,None), slowis exactlynnodes behind. This leads to since we startedslowat the dummy node,slow. This elegant trick eliminates the need to know the list length in advance.

Time and Space Complexity

  • Time complexity: O(L), but we only traverse the list once. This is a constant-factor improvement over the two-pass method.
  • Space complexity: O(1), as we only use a few extra pointers.

Edge Cases and Important Considerations

No matter which approach you choose, you must handle certain edge cases gracefully:

  • Removing the head node: If n equals the length of the list, the head is removed. The dummy node technique in the two-pointer method makes this trivial, as dummy.next will simply point to the second node.
  • List with only one node: If `n = 1

Completing the Single‑Node Scenario

When the list consists of a single element and n equals 1, the dummy node still points to the head, fast is advanced one step beyond the end (it becomes None), and slow remains at the dummy. The assignment slow.Still, next = slow. Also, next. Consider this: next therefore sets dummy. next to None, effectively returning an empty list. The function behaves exactly as intended without any extra branching The details matter here..

Handling Out‑of‑Range n Values

In a production‑ready implementation it is prudent to verify that n is within the valid range. If fast becomes None before the initial loop finishes (i.e.

  1. Raise an exception – signalling a misuse of the API, or
  2. Return the original list unchanged – keeping the operation safe but non‑destructive.

A concise check can be added right after the dummy setup:

# Verify that the list is long enough
for _ in range(n):
    if fast is None:          # not enough nodes
        return head           # or raise ValueError("n exceeds list length")
    fast = fast.next

A Quick Test Harness

Below is a minimal driver that exercises the routine on several representative inputs, illustrating both the typical case and the edge conditions discussed:

def build_list(values):
    dummy = ListNode(0)
    cur = dummy
    for v in values:
        cur.next = ListNode(v)
        cur = cur.next
    return dummy.next

def to_pylist(head):
    out = []
    while head:
        out.append(head.val)
        head = head.

# 1. Normal case – remove middle element
head = build_list([10, 20, 30, 40, 50])
new_head = removeNthFromEnd(head, 2)      # remove 40
print(to_pylist(new_head))               # [10, 20, 30, 50]

# 2. Remove the head
head = build_list([1, 2, 3])
new_head = removeNthFromEnd(head, 3)      # remove 1
print(to_pylist(new_head))               # [2, 3]

# 3. Single‑node list
head = build_list([7])
new_head = removeNthFromEnd(head, 1)      # remove 7
print(to_pylist(new_head))               # []

# 4. Invalid n (greater than length)
head = build_list([1, 2])
try:
    new_head = removeNthFromEnd(head, 5)
except ValueError as e:
    print(e)                             # n exceeds list length

Why the Two‑Pointer Technique Is Preferred

  • Single traversal guarantees the smallest possible constant factor in runtime.
  • No auxiliary data structures keep memory usage at a strict O(1).
  • Uniform handling of all positions (head, middle, tail) through the dummy node eliminates special‑case code, making the implementation easier to audit and maintain.

Final Thoughts

The two‑pointer method delivers an elegant, linear‑time solution to the “remove Nth node from end of list” problem while keeping the codebase lean. That's why by introducing a dummy sentinel, establishing a fixed gap between two pointers, and performing a single pass, developers obtain a strong routine that gracefully manages edge cases such as head removal and single‑element lists. When combined with a simple length check for out‑of‑range n, the function becomes both safe and efficient, embodying the ideal balance of clarity and performance in linked‑list algorithms That's the part that actually makes a difference..

Just Made It Online

Just Went Online

Based on This

These Fit Well Together

Thank you for reading about Remove Nth Node From End Of List. We hope the information has been useful. Feel free to contact us if you have any questions. See you next time — don't forget to bookmark!
⌂ Back to Home