Algorithm

Reorder List

Two Pointer Pattern

Reorder List

Reorder a list to follow the L0 -> Ln -> L1 -> Ln-1... pattern.

CONSTRAINTS
  • Nodes: 1 to 50,000
  • Must modify in-place.
EXAMPLE 1
Input: head = [1,2,3,4]
Output: [1,4,2,3]
The tail (4) is folded back after 1. The remaining sub-list follows.
Can this be done in one pass?
No. Because we need to access nodes from the end, we must either reverse the second half or use a stack/recursion, taking at least two logical passes.

We want to rearrange a singly linked list in-place so that it follows an alternating "outer-to-inner" pattern: first node, last node, second node, second-to-last node, and so on. However, because a linked list has no backward pointers and no direct indexing, we cannot easily read elements from the back of the list. How can we perform this intricate folding rearrangement without allocating extra memory?

The Reference Copy Tax

The most straightforward way is to copy all node references into a flat array. Once we have a list of references, we can use two pointers moving inward from both ends to reconnect the nodes in the desired alternating order.

While this runs in linear time, storing all the node references requires O(N) extra memory, which violates the in-place constraint and is highly inefficient for large lists.

python
# Copy all node references
nodes = []
curr = head
while curr:
    nodes.append(curr)
    curr = curr.next

# Reconnect using two pointers
left, right = 0, len(nodes) - 1
while left < right:
    nodes[left].next = nodes[right]
    left += 1
    if left == right:
        break
    nodes[right].next = nodes[left]
    right -= 1
nodes[left].next = None # Terminate list
Split, Reversal, and Splicer

To fold the list in-place with O(1) extra space, we use a three-phase surgery using these pointer states:
- Halving Pointers (slow, fast): Runners moving at 1x and 2x speeds to find the exact midpoint and split the list in half.
- Reversing Pointers (prev, curr, nxt): Standard states to reverse the second half of the list so it points backward from the tail.
- Splicing Pointers (p1, p2): Parallel heads pointing to the front of the first half and the front of the reversed second half.

The Halves Severance

To prevent infinite loops, we must explicitly sever the link between the first and second halves. After finding the midpoint with slow, we save the start of the second half (slow.next) and set slow.next = None. If we forget to sever this link, the last node of the first half will still point to the second half, creating a cycle in our final spliced structure.

The Interweaving

Once the second half is reversed, we have two independent strands: the original front half (p1) and the reversed tail half (p2). We merge them by alternating nodes: we splice a node from p2 between the current node of p1 and its original next node.

python
# Phase 1: Find the middle node
slow = head
fast = head
while fast and fast.next:
    slow = slow.next
    fast = fast.next.next

# Phase 2: Sever the halves and reverse the second half
curr = slow.next
slow.next = None # Sever the link
prev = None
while curr:
    nxt = curr.next
    curr.next = prev
    prev = curr
    curr = nxt

# Phase 3: Interweave both strands in-place
p1 = head
p2 = prev  # Head of the reversed second half

while p2:
    # Save the next destinations
    tmp1 = p1.next
    tmp2 = p2.next
    
    # Choreographed Splice
    p1.next = p2
    p2.next = tmp1
    
    # Advance pointers
    p1 = tmp1
    p2 = tmp2
Even and Odd Spans

The three-phase strategy handles lengths elegantly:
- Odd Lengths (e.g. [1, 2, 3]): The first half is [1, 2], and the reversed second half is [3]. During merge, 3 is spliced after 1. The result is [1, 3, 2], terminating correctly because p2 becomes null.
- Even Lengths (e.g. [1, 2, 3, 4]): The first half is [1, 2], and the reversed second half is [4, 3]. The result is [1, 4, 2, 3].

Worked Example:Folding the Strand
1
2
slow
3
4
fast
NULL
We find the midpoint using slow/fast pointers. slow lands on node 2, and fast reaches node 4.
1
p1
2
NULL
We sever the link after the midpoint node 2 (2.next = null). This leaves us with two independent lists: the first half [1, 2] and the second half [3, 4].
4
p2
3
NULL
We reverse the second half in-place. Node 4 now points to 3, and 3 points to null, giving us the reversed strand [4, 3].
1
4
p2
2
p1
NULL
We begin interweaving: we splice the first node of the reversed second half (4) directly after the first node of the first half (1). Node 1 now points to 4, and 4 points to 2.
1
4
2
3
NULL
We splice the next node of the reversed second half (3) directly after node 2. Node 2 now points to 3, and 3 points to null. Reordering is complete.
Interactive Strategy Visualization
LIST REORDER PROTOCOL

Recursive Folding Strategy

Fragment A
1
2
Fragment B
3
4

Process Step

Phase 1: Binary Fragmentation

We use the Slow & Fast technique to identify the exact midpoint. We then severe the list into two discrete fragments: List A and List B.

Folding Trick

We are essentially folding the list onto itself. Reversing the second half is what enables this symmetrical weave.

Strategy: Three-Stage Metamorphosis

1. Find Mid & Split → 2. Reverse Second Fragment → 3. Interleaved Zipper Merge.

O(N) Time · O(N) Space Array of Nodes
O(N) Time · O(1) Space Split, Reverse, Weave