Linked list row 1 = head's chain · row 2 = the cut-off second half · slash = next is null
public void reorderList(ListNode head) { ListNode slow = head; ListNode fast = head.next; // 1. find the middle while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; } ListNode second = slow.next; // 2. reverse the second half ListNode prev = null; slow.next = null; while (second != null) { ListNode tmp = second.next; second.next = prev; prev = second; second = tmp; } ListNode first = head; // 3. zip the halves second = prev; while (second != null) { ListNode tmp1 = first.next; ListNode tmp2 = second.next; first.next = second; second.next = tmp1; first = tmp1; second = tmp2; }}
- slow
- —
- fast
- —
- first
- —
- second
- —
- head chain
- —
Why it works
- Brute force copies the nodes into an array, then relinks them with two indices walking in from both ends. O(n) time but O(n) extra space for the array.
- The answer is two lists zipped together: the first half in order, and the second half backwards. A singly linked list cannot walk backwards, so reverse the second half once and the zip becomes a forward walk on both.
- Three linear passes, no extra storage: slow/fast finds the middle in n/2 hops, the reversal touches each second-half node once, and the zip touches each node once. O(n) time, O(1) space.
- Pitfall: cut the list at the middle (
slow.next = null). Without the cut the first half still runs into the second, and the zip builds a cycle. Startingfastathead.nextkeeps the extra node of an odd list in the first half. - Pitfall: save both next pointers first. Lines 22 and 23 overwrite
first.nextandsecond.next;tmp1andtmp2are the only handles left on the rest of each half. - Related: Middle of the Linked List (876), Reverse Linked List (206) and Merge Two Sorted Lists (21) are the three building blocks; Palindrome Linked List (234) uses the same find-middle-and-reverse trick.