Reverse Linked List – Solution & Complexity

Solution Walkthrough

  1. Step 1: Understand the Goal

    • The input is a chain of nodes: 1 -> 2 -> 3 -> null.
    • Reversing it means every next pointer should point the other way: 3 -> 2 -> 1 -> null.
    • The new head is the old tail, so the function must return the node that used to be last.
  2. Step 2: Track Three Pointers

    • Walking the list forward while rewriting next pointers destroys the way back unless you keep a reference to what came before.
    • Keep three pointers as you walk: prev (already-reversed portion), curr (node being processed), and next_node (saved before you overwrite curr.next).
    • Start with prev = None since the new tail's next must be null.
    def reverse_list(head):
        prev = None
        curr = head
        return prev
  3. Step 3: Rewire One Node at a Time

    • Save curr.next before overwriting it, so you don't lose the rest of the list.
    • Point curr.next backward at prev.
    • Advance both prev and curr one step forward for the next iteration.
    def reverse_list(head):
        prev = None
        curr = head
        while curr:
            next_node = curr.next
            curr.next = prev
            prev = curr
            curr = next_node
        return prev
  4. Step 4: Confirm the Loop Termination and Complexity

    • The loop stops when curr becomes None, meaning every original node has been rewired.
    • At that point prev holds the new head (the old tail), which is exactly what the function returns.
    • Each node is visited once, so time complexity is O(n); only three pointers are kept, so space complexity is O(1).
    class ListNode:
        def __init__(self, val=0, next=None):
            self.val = val
            self.next = next
    
    
    def reverse_list(head: ListNode) -> ListNode:
        prev = None
        curr = head
        while curr:
            next_node = curr.next
            curr.next = prev
            prev = curr
            curr = next_node
        return prev
  5. Step 5: Alternative: Recursive Reversal

    • Recursively reverse everything after the head first, then fix up the one link at the current level.
    • Base case: an empty list or single node is already reversed.
    • After the recursive call, head.next is the new tail, so set head.next.next = head and detach head.next to avoid a two-node cycle.
    • This trades the O(1) space of the iterative version for O(n) call-stack space.
    def reverse_list(head: ListNode) -> ListNode:
        if head is None or head.next is None:
            return head
        new_head = reverse_list(head.next)
        head.next.next = head
        head.next = None
        return new_head

FAQ