Compare the two patterns
// Returns second middle
slow = head;
fast = head;
// Returns first middle for even-length lists
slow = head;
fast = head.next;For odd length, both end up at the same middle:
1 → 2 → 3 → 4 → 5
↑let slow = head;
let fast = head;
while (fast && fast.next) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
let slow = head;
let fast = head.next;
while (fast && fast.next) {
slow = slow.next;
fast = fast.next.next;
}
return slow;The key difference is starting fast = head.next instead of fast = head.
For an even list
1 → 2 → 3 → 4 → 5 → 6With fast = head.next:
Start:
slow = 1
fast = 2
Iteration 1:
slow = 2
fast = 4
Iteration 2:
slow = 3
fast = 6
stop → fast.next is nullSo:
1 → 2 → 3 → 4 → 5 → 6
↑ ↑
slow second halfslow ends at 3, the first middle.
This is especially useful when you want to split the linked list into two halves:
let second = slow.next;
slow.next = null;giving:
1 → 2 → 3
4 → 5 → 6Compare the two patterns
// Returns second middle
slow = head;
fast = head;
// Returns first middle for even-length lists
slow = head;
fast = head.next;For odd length, both end up at the same middle:
1 → 2 → 3 → 4 → 5
↑So for problems like Reorder List, where you want to split the list cleanly, fast = head.next is a very convenient pattern.