You are given the head of a singly linked list. Your task is to reorder the list into the following pattern:
L0 → L1 → L2 → ... → Ln-1 → Ln
becomes:
L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → ...
You must:
- modify the list in-place
- not change node values
- only reorder node links
Example:
Input: 1 → 2 → 3 → 4 Output: 1 → 4 → 2 → 3
Another:
Input: 1 → 2 → 3 → 4 → 5 Output: 1 → 5 → 2 → 4 → 3
Problem Understanding
Key observations:
- The first half stays in order
- The second half appears in reverse order
- Nodes alternate between front and back halves
- Linked list structure makes random access difficult
- We cannot use arrays to rebuild (violates in-place requirement)
So we need a linked-list–friendly strategy.
Logic Explained in Simple English
To reorder the list, a clean strategy is:
Step 1: Split the list into two halves
- Use slow/fast pointers
- When fast reaches end, slow is at midpoint
Step 2: Reverse the second half of the list
- Standard linked list reversal
- Now we have:
- first half in original order
- second half in reversed order
Step 3: Merge the two halves alternately
Take nodes:
from first half, then from second half, repeatedly
Why this works:
- Splitting isolates first and last nodes
- Reversing prepares nodes in correct backward order
- Merging alternates references without extra space
This avoids index access and follows linked list constraints perfectly.
Step-by-Step Approach
- Edge case: if list has 0 or 1 node → return immediately
- Use slow/fast pointers to find middle
- Split list into two halves
- Reverse second half
- Interleave nodes:
- first.next = second
- second.next = first.next (saved)
- Stop when second half fully merged
Java Implementation
class Solution {
public void reorderList(ListNode head) {
if (head == null || head.next == null) return;
// Step 1: find middle
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
// Step 2: reverse second half
ListNode prev = null;
ListNode curr = slow.next;
slow.next = null; // split the list
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
// Step 3: merge two halves
ListNode first = head;
ListNode second = prev;
while (second != null) {
ListNode temp1 = first.next;
ListNode temp2 = second.next;
first.next = second;
second.next = temp1;
first = temp1;
second = temp2;
}
}
}
Dry Run Example
Input list:
1 → 2 → 3 → 4 → 5
Step 1 — Find middle
Slow ends at 3
Split into:
First: 1 → 2 → 3 Second: 4 → 5
Step 2 — Reverse second half
Second becomes:
5 → 4
Step 3 — Merge alternately
Merge sequence:
1 → 5 → 2 → 4 → 3
Final reordered list:
1 → 5 → 2 → 4 → 3
Time and Space Complexity
Time Complexity
O(n)
Finding middle: O(n)
Reversing: O(n)
Merging: O(n)
Space Complexity
O(1)
No extra data structures used
Common Mistakes and How to Avoid Them
Mistake 1: Reversing the entire list
Only reverse second half, not entire list.
Mistake 2: Not breaking the list into two parts
If you don’t set:
slow.next = null
you get infinite loops.
Mistake 3: Using arrays or extra lists
Violates in-place requirement.
Mistake 4: Off-by-one midpoint handling
Fast/slow approach ensures proper split for even and odd lengths.
Mistake 5: Incorrect merge termination
Stop merging when second half finishes.
