Day 60: Python Remove Nth Node From End of Linked List, Two-Pointer Magic to Delete in One Pass (LeetCode #19 Style)

Published: (December 10, 2025 at 07:09 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

Day 60 – Remove Nth Node From End of Linked List

Welcome to Day 60 of the #80DaysOfChallenges journey! This intermediate challenge solves the iconic Remove Nth Node From End of Linked List problem (LeetCode #19) using a two‑pointer technique that finds and deletes the target node in a single pass with O(1) extra space. The solution includes a Node class, helper functions for building and printing a linked list, and a main routine for interactive testing.

Example
List 1 → 2 → 3 → 4 → 5, n = 21 → 2 → 3 → 5 (remove 4, the second node from the end)

Key Takeaways

Node Class and Builder: Easy List Construction

class Node:
    """Simple singly linked list node."""
    def __init__(self, value: int):
        self.value = value
        self.next = None
def build_linked_list(values: list[int]) -> Node:
    """Build a linked list from a list of integers."""
    if not values:
        return None

    head = Node(values[0])
    curr = head
    for v in values[1:]:
        curr.next = Node(v)
        curr = curr.next
    return head

O(n) build time; gracefully handles an empty input list.

Removal Function: Dummy Head and Two‑Pointer Dance

def remove_nth_from_end(head: Node, n: int) -> Node:
    """
    Remove the Nth node from the end using fast/slow pointers.
    Returns the new head after deletion.
    """
    dummy = Node(0)          # Simplifies edge cases (e.g., deleting the head)
    dummy.next = head
    fast = dummy
    slow = dummy

    # Move fast pointer n+1 steps ahead
    for _ in range(n + 1):
        if fast is None:
            return head      # n is larger than the list length
        fast = fast.next

    # Advance both pointers until fast reaches the end
    while fast is not None:
        fast = fast.next
        slow = slow.next

    # Delete the target node
    slow.next = slow.next.next
    return dummy.next

The dummy node removes the need for special‑case handling of head deletion. By advancing fastn+1 steps, slow ends up just before the node to delete, enabling a single‑pass O(n) solution.

Printer and Main: Visualization and Input

def print_linked_list(head: Node) -> None:
    """Print linked list values cleanly."""
    curr = head
    nodes = []
    while curr is not None:
        nodes.append(str(curr.value))
        curr = curr.next
    print(f"Linked List: {' -> '.join(nodes)}")
# Interactive demo
raw_nums = input("Enter list values (space-separated): ").strip()
raw_n = input("Enter n (which node from the end to remove): ").strip()

if not raw_nums or not raw_n:
    print("Invalid input. Exiting.")
    exit()

nums = list(map(int, raw_nums.split()))
n = int(raw_n)

head = build_linked_list(nums)
print("Original list:")
print_linked_list(head)

new_head = remove_nth_from_end(head, n)
print(f"List after removing {n}th node from the end:")
print_linked_list(new_head)

The script parses space‑separated integers, builds the list, displays the original structure, performs the removal, and prints the resulting list.

Summary and Reflections

This problem showcases the elegance of the two‑pointer technique for accessing elements from the end of a singly linked list without first computing its length.

  • Dummy head utility – eliminates edge‑case checks for head deletion.
  • Pointer spacing – keeping fastn+1 nodes ahead aligns slow perfectly before the target.
  • One‑pass efficiency – O(n) time, O(1) extra space.

Recursive approaches are possible but iterative solutions are safer for deep lists.

Next Steps and Resources

Back to Blog

Related posts

Read more »