← Back to DevBytes

Solving Reorder List in Python: Step-by-Step Guide

Introduction to the Reorder List Problem

The Reorder List problem is a classic linked list manipulation challenge frequently encountered in coding interviews and algorithm practice platforms like LeetCode. Given a singly linked list L0 → L1 → … → Ln - 1 → Ln, the task is to reorder it in-place to L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …. You may not modify the values in the list's nodes—only the next pointers themselves may be changed.

While the problem statement sounds simple, it elegantly tests multiple foundational linked list skills at once: finding the middle, reversing a list, and merging two lists. Mastering it builds a strong mental model for pointer manipulation that transfers to many real-world scenarios.

Why This Problem Matters

Understanding the Problem With an Example

Suppose you are given the linked list 1 → 2 → 3 → 4 → 5. After reordering, the expected output is 1 → 5 → 2 → 4 → 3. Notice how the first node connects to the last, the second to the second-to-last, and so on, until the middle node is left at the end.

For an even-length list like 1 → 2 → 3 → 4, the result becomes 1 → 4 → 2 → 3. The middle element naturally falls into place without any special handling.

Breaking Down the Solution Strategy

The most efficient approach splits the problem into three distinct phases. Each phase is a well-known linked list operation on its own, which makes the overall solution easier to reason about and test.

Step 1: Find the Middle of the List

Use the slow and fast pointer technique. The slow pointer advances one node at a time while the fast pointer advances two. When the fast pointer reaches the end, the slow pointer will be at the middle. This runs in O(n) time and O(1) space.

Step 2: Reverse the Second Half

Starting from the middle node, reverse the second half of the list. After reversal, you will have two separate lists: the first half in original order and the second half in reversed order.

Step 3: Merge the Two Halves Alternately

Traverse both lists simultaneously, alternating nodes from the first half and the reversed second half. Adjust the next pointers carefully to avoid losing references.

Defining the Linked List Node

Before writing the solution, define the node structure. Most interview platforms provide this, but understanding it is essential.

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

def build_list(values):
    """Helper to build a linked list from a Python list."""
    dummy = ListNode()
    current = dummy
    for v in values:
        current.next = ListNode(v)
        current = current.next
    return dummy.next

def to_list(head):
    """Helper to convert a linked list back to a Python list."""
    result = []
    while head:
        result.append(head.val)
        head = head.next
    return result

Complete Solution Implementation

Below is the full implementation combining all three steps. Each phase is isolated into its own method for clarity and testability.

class Solution:
    def reorderList(self, head):
        """
        Reorders the linked list in-place.
        Do not return anything, modify head in-place instead.
        """
        if not head or not head.next:
            return

        # Step 1: Find the middle using slow and fast pointers
        slow = head
        fast = head
        while fast.next and fast.next.next:
            slow = slow.next
            fast = fast.next.next

        # Step 2: Reverse the second half of the list
        second = self.reverse(slow.next)
        slow.next = None  # Cut the first half from the second

        # Step 3: Merge the two halves alternately
        first = head
        while second:
            tmp1 = first.next
            tmp2 = second.next
            first.next = second
            second.next = tmp1
            first = tmp1
            second = tmp2

    def reverse(self, node):
        """Reverses a linked list starting at the given node."""
        prev = None
        current = node
        while current:
            nxt = current.next
            current.next = prev
            prev = current
            current = nxt
        return prev

Walking Through the Code

Let's trace the algorithm with the input 1 → 2 → 3 → 4 → 5:

Testing the Solution

Always test with multiple cases, including edge cases like empty lists, single-node lists, and even-length lists.

if __name__ == "__main__":
    sol = Solution()

    # Test 1: Odd-length list
    head1 = build_list([1, 2, 3, 4, 5])
    sol.reorderList(head1)
    print(to_list(head1))  # Output: [1, 5, 2, 4, 3]

    # Test 2: Even-length list
    head2 = build_list([1, 2, 3, 4])
    sol.reorderList(head2)
    print(to_list(head2))  # Output: [1, 4, 2, 3]

    # Test 3: Single node
    head3 = build_list([1])
    sol.reorderList(head3)
    print(to_list(head3))  # Output: [1]

    # Test 4: Two nodes
    head4 = build_list([1, 2])
    sol.reorderList(head4)
    print(to_list(head4))  # Output: [1, 2]

    # Test 5: Empty list
    head5 = build_list([])
    sol.reorderList(head5)
    print(to_list(head5))  # Output: []

Complexity Analysis

Understanding the time and space complexity is crucial for evaluating any solution.

Best Practices and Common Pitfalls

Best Practices

Common Pitfalls

Alternative Approaches

While the three-step approach is optimal, it is worth knowing alternatives for context.

Using a Stack

You can traverse the list once, push all nodes onto a stack, then pop from the stack while traversing again to reorder. This is simpler to implement but uses O(n) extra space, violating the in-place constraint.

def reorderListWithStack(self, head):
    if not head:
        return
    stack = []
    current = head
    while current:
        stack.append(current)
        current = current.next

    current = head
    n = len(stack) // 2
    while n > 0:
        top = stack.pop()
        nxt = current.next
        current.next = top
        top.next = nxt
        current = nxt
        n -= 1
    current.next = None

Recursive Approach

A recursive solution can also work by traversing to the end and rewiring pointers on the way back. However, recursion uses O(n) stack space and risks stack overflow for very long lists, making it impractical for production use.

Conclusion

The Reorder List problem is a powerful exercise that consolidates three essential linked list techniques into a single, elegant solution. By breaking it down into finding the middle, reversing the second half, and merging alternately, you create code that is both efficient and easy to understand. Remember to handle edge cases carefully, preserve references during pointer manipulation, and always test with lists of varying lengths. With these practices in place, you will be well-equipped to tackle this problem confidently in interviews and apply the same pointer-manipulation skills to more complex data structure challenges.

🛠 Tools from DevBytes

Inventory Tracker Pro — Excel inventory system, low-stock alerts · $19
AI Dev Kit for Mac — local AI dev environment templates · $9.99
KeyMapper for Mac — custom keyboard shortcut toolkit · $7.99

← Back to all articles