Linked list problems often look intimidating because they require manipulating pointers instead of values. LeetCode 143: Reorder List is a great example where understanding pointer operations is much more important than memorizing code.

In this article, we’ll break the problem into simple steps and explain why the solution works.


Problem Statement

Given the head of a singly linked list, reorder it from:

L0 → L1 → L2 → ... → Ln

to

L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → ...

The important constraint is:

You cannot modify the values inside the nodes—you must rearrange the nodes themselves.

Example 1

Input:
2 → 4 → 6 → 8

Output:
2 → 8 → 4 → 6

Example 2

Input:
2 → 4 → 6 → 8 → 10

Output:
2 → 10 → 4 → 8 → 6

Observing the Pattern

Let’s look at the node positions.

Original:

0 → 1 → 2 → 3 → 4 → 5 → 6

Expected:

0 → 6 → 1 → 5 → 2 → 4 → 3

Notice something interesting:

  • We keep taking one node from the front.
  • Then one node from the back.
  • Repeat until all nodes are used.

The challenge is that a singly linked list only allows moving forward. We can’t simply jump to the last node whenever we want.

So how do we efficiently access both ends?

The trick is to transform the list into a form that’s easy to merge.


The Three-Step Approach

The solution can be divided into three independent steps:

  1. Find the middle of the list.
  2. Reverse the second half.
  3. Merge the two halves alternately.

Let’s go through each one.


Step 1: Find the Middle

We use the classic slow and fast pointer technique.

slow, fast = head, head.next

while fast and fast.next:
    slow = slow.next
    fast = fast.next.next
  • slow moves one step.
  • fast moves two steps.

When fast reaches the end, slow will be at the middle.

For example:

1 → 2 → 3 → 4 → 5 → 6

After traversal:

slow
  ↓
1 → 2 → 3 → 4 → 5 → 6

The list is now split into:

First:
1 → 2 → 3

Second:
4 → 5 → 6

We disconnect them:

second = slow.next
slow.next = None

Now we have two independent linked lists.


Step 2: Reverse the Second Half

Currently the second half is:

4 → 5 → 6

But we need to access nodes from the end first:

6 → 5 → 4

So we reverse it.

prev = None

while second:
    tmp = second.next
    second.next = prev
    prev = second
    second = tmp

After reversing:

6 → 5 → 4

Now the first list is

1 → 2 → 3

and the reversed second list is

6 → 5 → 4

This makes alternating between front and back straightforward.


Step 3: Merge Both Lists

Now we simply weave the two lists together.

Before merging:

First:
1 → 2 → 3

Second:
6 → 5 → 4

Iteration 1:

1 → 6

Iteration 2:

1 → 6 → 2 → 5

Iteration 3:

1 → 6 → 2 → 5 → 3 → 4

Implementation:

first, second = head, prev

while second:
    tmp1 = first.next
    tmp2 = second.next

    first.next = second
    second.next = tmp1

    first = tmp1
    second = tmp2

Notice how we store the next pointers before changing them. Without these temporary variables, we’d lose access to the remaining nodes.


Complete Solution

class Solution:
    def reorderList(self, head: Optional[ListNode]) -> None:
        slow, fast = head, head.next

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

        second = slow.next
        prev = slow.next = None

        # Step 2: Reverse second half
        while second:
            tmp = second.next
            second.next = prev
            prev = second
            second = tmp

        # Step 3: Merge the two halves
        first, second = head, prev

        while second:
            tmp1, tmp2 = first.next, second.next

            first.next = second
            second.next = tmp1

            first, second = tmp1, tmp2

Complexity Analysis

Time Complexity

Finding the middle:

O(n)

Reversing the second half:

O(n)

Merging:

O(n)

Overall:

O(n)

Space Complexity

We only use a few pointers regardless of the list size.

O(1)

No extra arrays, stacks, or recursion are used.


Why This Solution Is Elegant

At first glance, the problem seems to require repeatedly finding the last node, which would lead to an inefficient O(n²)solution.

Instead, we:

  • Find the midpoint once.
  • Reverse the second half once.
  • Merge both halves once.

Each node is visited only a constant number of times, making the solution both efficient and easy to reason about.

This “Split → Reverse → Merge” pattern is one of the most common linked list techniques you’ll encounter in coding interviews. Mastering it will help you solve several other problems involving linked list reordering and manipulation.