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 → 6

With fast = head.next:

Start:
slow = 1
fast = 2
 
Iteration 1:
slow = 2
fast = 4
 
Iteration 2:
slow = 3
fast = 6
 
stop → fast.next is null

So:

1 → 2 → 3 → 4 → 5 → 6
        ↑   ↑
      slow  second half

slow 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 → 6

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

So for problems like Reorder List, where you want to split the list cleanly, fast = head.next is a very convenient pattern.