Reorder List
You are given the values of the nodes of a singly linked list L0 -> L1 -> ... -> Ln-1 -> Ln. Reorder the list to be on the following form: L0 -> Ln -> L1 -> Ln-1 -> L2 -> Ln-2 -> ... You may not modify the values in the list's nodes. Only nodes themselves may be changed. Find the middle with fast and slow pointers , reverse the second half, then weave-merge the two halves alternately .
Constraints
- The number of nodes in the list is in the range [1, 5 × 104].
- 1 ≤ valuesi ≤ 1000
Example
values = [1, 2, 3, 4][1, 4, 2, 3]Explanation Splitting the list into [1,2] and [3,4], reversing the second half to [4,3], and weaving them alternately gives 1 -> 4 -> 2 -> 3.
In plain terms
- Linked list
- A chain of nodes where each node just points to the next one, unlike an array where all the values sit together in one contiguous block.
Find the middle, reverse the second half, then weave-merge
slow and fast both start at index 0 (value 1).
What happens in this step
values = [1, 2, 3, 4] slow = 0, fast = 0 Loop condition: "while fast.next && fast.next.next" — fast still has two more nodes ahead, so the loop runs.
Steps to visualize
- Use fast and slow pointers to find the middle node of the list.
- Split the list into two halves at the middle.
- Reverse the second half in place.
- Weave the two halves together, alternating one node from each.
- Walk the final list to read off the reordered values.
Walk through the code
Same walkthrough, now with the code. Press Next to move one step and watch which lines run.
slow and fast both start at index 0 (value 1).
What happens in this step
values = [1, 2, 3, 4] slow = 0, fast = 0 Loop condition: "while fast.next && fast.next.next" — fast still has two more nodes ahead, so the loop runs.
Solution
function reorderList(values) {
if (values.length === 0) {
return [];
}
const nodes = values.map((val) => ({ val, next: null }));
for (let i = 0; i < nodes.length - 1; i++) {
nodes[i].next = nodes[i + 1];
}
let slow = nodes[0];
let fast = nodes[0];
while (fast.next !== null && fast.next.next !== null) {
slow = slow.next;
fast = fast.next.next;
}
let second = slow.next;
slow.next = null;
let prev = null;
while (second !== null) {
const next = second.next;
second.next = prev;
prev = second;
second = next;
}
second = prev;
let first = nodes[0];
while (second !== null) {
const firstNext = first.next;
const secondNext = second.next;
first.next = second;
second.next = firstNext;
first = firstNext;
second = secondNext;
}
const result = [];
let node = nodes[0];
while (node !== null) {
result.push(node.val);
node = node.next;
}
return result;
}- Time
- O(n)
- Space
- O(1) (excluding the constructed list and result array)
Test cases
| Input | Expected | Covers |
|---|---|---|
values = [1, 2, 3, 4] | [1, 4, 2, 3] | example from the docstring, even length |
values = [1, 2, 3, 4, 5] | [1, 5, 2, 4, 3] | odd-length list with a single true middle node |
values = [1, 2] | [1, 2] | smallest interesting case: only two nodes |
values = [1] | [1] | smallest valid input: a single node |
values = [1, 2, 3, 4, 5, 6] | [1, 6, 2, 5, 3, 4] | a larger even-length list |
values = [2, 2, 2, 2] | [2, 2, 2, 2] | every node holding the same value |