150NeetCode 150

37.Reorder List

MediumBlind 75Linked List · 3/11

Problem

You are given the head of a singly linked list L0 → L1 → … → Ln-1 → Ln. Reorder it in place to:

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

That is, alternate between taking a node from the front and a node from the back. You may not change node values — only the next pointers. The function returns nothing.

Examples

Input:  head = [1, 2, 3, 4]
Output: [1, 4, 2, 3]
Explanation: front 1, back 4, front 2, back 3.
Input:  head = [1, 2, 3, 4, 5]
Output: [1, 5, 2, 4, 3]
Explanation: front 1, back 5, front 2, back 4, then the middle node 3.

Constraints

  • The number of nodes in the list is in the range [1, 5 * 10^4].
  • 1 <= Node.val <= 1000

💡 Key Insight

The answer interleaves the first half with the second half reversed. A singly linked list cannot walk backwards, but we can make the back half walkable from the end by reversing it. So: find the middle (slow/fast pointers), reverse the second half, then merge the two halves alternately — three classic O(n), O(1)-space linked-list moves.

Brute Force (Repeatedly Find the Tail)

TimeO(n²)SpaceO(1)

Intuition

Do exactly what the problem says: at the current node, walk to the end of the list, detach the last node and insert it right after the current node. Then jump two nodes ahead and repeat.

Algorithm

  1. curr = head.
  2. While curr and curr.next and curr.next.next exist:
    • Walk to find the second-to-last node prev and the last node last.
    • Detach: prev.next = null.
    • Insert: last.next = curr.next, curr.next = last.
    • curr = last.next (skip over the inserted node).

Visualization

1 -> 2 -> 3 -> 4 -> 5
curr=1: move 5 after 1 -> 1 -> 5 -> 2 -> 3 -> 4
curr=2: move 4 after 2 -> 1 -> 5 -> 2 -> 4 -> 3
curr=3: 3.next is null -> stop

Code

java
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public void reorderList(ListNode head) {
        ListNode curr = head;
        while (curr != null && curr.next != null && curr.next.next != null) {
            // Find the second-to-last node
            ListNode prev = curr;
            while (prev.next.next != null) {
                prev = prev.next;
            }
            ListNode last = prev.next;
            prev.next = null;       // detach the tail
            last.next = curr.next;  // insert it after curr
            curr.next = last;
            curr = last.next;       // move to the next front node
        }
    }
}

Complexity

  • Time: O(n²) — each of ~n/2 iterations walks to the tail.
  • Space: O(1) — pointer manipulation only.

Complexity Comparison

Approach Time Space
Repeatedly Find the Tail O(n²) O(1)
Array + Two Pointers O(n) O(n)
Middle + Reverse + Merge O(n) O(1)

Common Pitfalls

  • Forgetting slow.next = null when splitting — the first half still points into the second half, creating a cycle after the merge.
  • Starting fast at head instead of head.next changes where slow stops; that still works only if you split consistently, so trace a 2-node and 3-node list.
  • In the array version, not setting the final node's next to null, leaving a cycle.
  • Merging with while (first != null) instead of while (second != null) — the first half can be one node longer, so loop on the shorter half.
  • Creating new nodes or swapping values — the problem requires rewiring the existing nodes.