0Pricing
DSA Interview Prep · Lesson

Reversing a Linked List

Reverse a singly linked list iteratively with three-pointer rewiring and recursively, tracing each step on a whiteboard-style diagram.

Reversing a Linked List is a free DSA Interview Prep lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the DSA Interview Prep learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Why List Reversal Is Essential

Reversing a linked list is among the most frequently asked coding interview questions. It tests your ability to manipulate pointers precisely without losing track of nodes. Variants appear as standalone problems and as sub-steps inside larger algorithms like palindrome detection, reorder list, and k-group reversal.

The iterative approach uses three pointers: prev, curr, and next_node. The recursive approach expresses the same logic as a call-stack traversal. Both achieve O(n) time and, for iterative, O(1) space.

Three-Pointer Iterative Reversal

At each step of the iterative reversal: save curr.next so you do not lose the rest of the list, flip curr.next to point backward to prev, advance prev to curr, and advance curr to the saved next. When curr becomes None the loop ends and prev is the new head.

A useful mnemonic: Save, Flip, Advance, Advance.

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def reverse_list(head):
    prev, curr = None, head
    while curr:
        next_node  = curr.next   # Save
        curr.next  = prev        # Flip
        prev       = curr        # Advance prev
        curr       = next_node   # Advance curr
    return prev  # new head

# Test
nodes = [ListNode(i) for i in range(1, 6)]
for i in range(len(nodes) - 1):
    nodes[i].next = nodes[i+1]
head = reverse_list(nodes[0])
while head:
    print(head.val, end=' ')  # 5 4 3 2 1
    head = head.next

Step-by-Step Trace

Let us trace reverse_list on 1 -> 2 -> 3. Initially prev=None, curr=1. Step 1: save next=2, flip 1.next=None, prev=1, curr=2. Step 2: save next=3, flip 2.next=1, prev=2, curr=3. Step 3: save next=None, flip 3.next=2, prev=3, curr=None. Loop ends; return prev=3, which is the new head of 3 -> 2 -> 1.

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def reverse_list_traced(head):
    prev, curr = None, head
    step = 0
    while curr:
        step += 1
        next_node = curr.next
        curr.next = prev
        print(f'Step {step}: flipped {curr.val}.next -> {prev.val if prev else None}')
        prev = curr
        curr = next_node
    return prev

nodes = [ListNode(i) for i in [1, 2, 3]]
for i in range(len(nodes) - 1):
    nodes[i].next = nodes[i+1]
head = reverse_list_traced(nodes[0])
print('New head:', head.val)  # 3

Recursive Reversal

The recursive approach trusts that reverse_list(head.next) returns the new head of the already-reversed suffix. All that remains is to flip the pointer between head and head.next: set head.next.next = head (point the old second node back to the old first) and head.next = None (sever the old forward link). The new head bubbles up from the base case.

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def reverse_list_rec(head):
    # Base case: empty or single node
    if not head or not head.next:
        return head
    new_head = reverse_list_rec(head.next)  # reverse suffix
    head.next.next = head   # former second node points back
    head.next = None        # sever forward link
    return new_head

nodes = [ListNode(i) for i in range(1, 5)]
for i in range(len(nodes) - 1):
    nodes[i].next = nodes[i+1]
head = reverse_list_rec(nodes[0])
while head:
    print(head.val, end=' ')  # 4 3 2 1
    head = head.next

Reversing a Sub-List (LeetCode 92)

LeetCode 92 'Reverse Linked List II' asks you to reverse the sub-list from position left to right (1-indexed) in one pass. The trick is to locate the node before the sub-list (use a dummy head so this is always valid), then perform the three-pointer reversal for exactly (right - left) steps, and finally reconnect the reversed segment to the surrounding list.

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def reverseBetween(head, left, right):
    dummy = ListNode(0, head)
    pre = dummy
    # Advance pre to node just before position 'left'
    for _ in range(left - 1):
        pre = pre.next
    curr = pre.next
    for _ in range(right - left):
        next_node   = curr.next
        curr.next   = next_node.next
        next_node.next = pre.next
        pre.next    = next_node
    return dummy.next

nodes = [ListNode(i) for i in range(1, 6)]
for i in range(len(nodes) - 1):
    nodes[i].next = nodes[i+1]
head = reverseBetween(nodes[0], 2, 4)
while head:
    print(head.val, end=' ')  # 1 4 3 2 5
    head = head.next

Reverse Nodes in K-Group (LeetCode 25)

LeetCode 25 'Reverse Nodes in k-Group' reverses every consecutive group of k nodes. The approach: check if k nodes remain; if not, leave them as-is. Reverse the next k nodes using the iterative method, then recursively reverse the remaining list and connect it. The time complexity remains O(n) with O(n/k) recursive call depth.

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def reverseKGroup(head, k):
    # Check if k nodes are available
    curr, count = head, 0
    while curr and count < k:
        curr = curr.next
        count += 1
    if count < k:
        return head   # fewer than k nodes left, keep as-is
    # Reverse k nodes
    prev, curr = None, head
    for _ in range(k):
        nxt = curr.next
        curr.next = prev
        prev = curr
        curr = nxt
    # head is now the tail of the reversed group
    head.next = reverseKGroup(curr, k)
    return prev

nodes = [ListNode(i) for i in range(1, 6)]
for i in range(len(nodes) - 1):
    nodes[i].next = nodes[i+1]
head = reverseKGroup(nodes[0], 2)
while head:
    print(head.val, end=' ')  # 2 1 4 3 5
    head = head.next

Palindrome Linked List

LeetCode 234 'Palindrome Linked List': check if a linked list is a palindrome in O(n) time, O(1) space. Strategy: find the midpoint with slow-fast pointers, reverse the second half in place, compare the two halves node by node, then optionally restore the list. This chains together midpoint finding and reversal — two foundational skills.

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def isPalindrome(head):
    # Find mid
    slow = fast = head
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
    # Reverse second half
    prev, curr = None, slow
    while curr:
        nxt = curr.next
        curr.next = prev
        prev = curr
        curr = nxt
    # Compare
    left, right = head, prev
    while right:
        if left.val != right.val:
            return False
        left  = left.next
        right = right.next
    return True

def build(arr):
    d = ListNode(0)
    c = d
    for v in arr:
        c.next = ListNode(v)
        c = c.next
    return d.next

print(isPalindrome(build([1,2,2,1])))  # True
print(isPalindrome(build([1,2,3])))    # False

Iterative vs Recursive Comparison

The iterative reversal uses O(1) space and is generally preferred. The recursive reversal uses O(n) stack space due to call depth, which can cause a stack overflow for very long lists (Python's default limit is ~1000 recursion levels).

In an interview, implement the iterative version first to show awareness of space constraints, then mention the recursive version as a cleaner alternative if the list length is bounded.

import sys
print('Default recursion limit:', sys.getrecursionlimit())
# For a list of 10,000 nodes the recursive reversal would hit this limit
# Iterative reversal has no such constraint

# Increase if needed (use sparingly):
# sys.setrecursionlimit(20000)

Common Mistakes in Reversal

Three mistakes account for almost all reversal bugs. First, not saving next before overwriting: curr.next = prev destroys the forward reference if next_node was not saved. Second, not returning prev: at the end of the loop, curr is None but prev is the new head. Third, wrong recursive base case: forgetting not head.next means a single-node list is not handled and causes an AttributeError.

# Minimal correct iterative reversal — annotated against common bugs
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def reverse_list(head):
    prev, curr = None, head
    while curr:
        next_node = curr.next   # BUG if omitted: lose rest of list
        curr.next = prev
        prev      = curr
        curr      = next_node
    return prev               # BUG if you return curr: it is None

nodes = [ListNode(i) for i in [1, 2, 3]]
nodes[0].next = nodes[1]
nodes[1].next = nodes[2]
h = reverse_list(nodes[0])
while h:
    print(h.val, end=' ')  # 3 2 1
    h = h.next

Reorder List (LeetCode 143)

LeetCode 143 'Reorder List' rearranges L0 → L1 → L2 → ... → Ln into L0 → Ln → L1 → Ln-1 → L2 → Ln-2 in O(n) time, O(1) space. The solution combines three steps: find the midpoint, reverse the second half, and interleave the two halves. Mastering reversal makes this seemingly complex problem a straightforward combination of familiar tools.

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def reorderList(head):
    if not head or not head.next:
        return
    # Find mid
    slow = fast = head
    while fast.next and fast.next.next:
        slow = slow.next
        fast = fast.next.next
    # Reverse second half
    prev, curr = None, slow.next
    slow.next = None
    while curr:
        nxt = curr.next
        curr.next = prev
        prev = curr
        curr = nxt
    # Interleave
    first, second = head, prev
    while second:
        tmp1, tmp2 = first.next, second.next
        first.next = second
        second.next = tmp1
        first, second = tmp1, tmp2

nodes = [ListNode(i) for i in range(1, 5)]
for i in range(len(nodes) - 1):
    nodes[i].next = nodes[i+1]
reorderList(nodes[0])
h = nodes[0]
while h:
    print(h.val, end=' ')  # 1 4 2 3
    h = h.next

Summary: Reversal Is a Building Block

Linked list reversal is rarely the final goal — it is a building block. Palindrome detection, k-group reversal, reorder list, and reverse between positions all rely on the same three-pointer iterative pattern. Once the pattern is automatic you can focus mental bandwidth on the higher-level problem structure.

Always practise reversal until you can write it from memory in under two minutes; it will appear in some form in nearly every linked-list interview round.

Quick Check

Test your understanding of Data Structures & Algorithms — Coding Interview Prep concepts from this lesson.

Lesson Recap

In this lesson you learned: the iterative Save-Flip-Advance-Advance pattern reverses a list in O(n) time and O(1) space, the recursive approach trusts the suffix is already reversed and only fixes the last link, and reversal is a core sub-step in palindrome detection, reorder list, and k-group reversal. Next up we explore cycle detection with Floyd's algorithm.

Frequently asked questions

Is the “Reversing a Linked List” lesson free?

Yes — the full text of “Reversing a Linked List” is free to read here on the web, and the DSA Interview Prep course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the DSA Interview Prep course, upgrade to CoddyKit PRO.

What will I learn in “Reversing a Linked List”?

Reverse a singly linked list iteratively with three-pointer rewiring and recursively, tracing each step on a whiteboard-style diagram. You practise DSA Interview Prep with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start DSA Interview Prep?

No prior experience is required. DSA Interview Prep on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Reversing a Linked List” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this DSA Interview Prep lesson?

Yes. Every DSA Interview Prep lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Node Class and List Construction
  2. Reversing a Linked List
  3. Cycle Detection with Floyd's Algorithm
  4. Merge, Split, and Find Nth from End
← Back to DSA Interview Prep