Problem
Given a singly linked list, find and return its middle node. If the list has an even number of nodes (two possible midpoints), return the second one.
[1,2,3,4,5]
- Input: head = [1, 2, 3, 4, 5]
- Output: node with value 3
- Explanation: The list has 5 nodes; the middle is the 3rd.
[1,2,3,4,5,6]
- Input: head = [1, 2, 3, 4, 5, 6]
- Output: node with value 4
- Explanation: There are two midpoints (3 and 4); return the second.
Intuition
The challenge is finding the middle in a single pass without knowing the total length upfront. If a slow runner moves one step at a time while a fast runner moves two steps, by the time the fast runner reaches the end of the list, the slow runner is exactly at the middle โ no counting required.
Solution โ Slow and Fast Pointer
Start both pointers at the head. Advance slow by one step and fast by two on each iteration. Stop when fast can no longer move forward (it has reached or passed the last node). Slow is now at the middle.
- Initialize both
slowandfastto head. - While
fastis not null andfast.nextis not null, advanceslowone step andfasttwo steps. - Return
slow.
1class Solution:
2 def middleNode(self, head: ListNode) -> ListNode:
3 slow = head
4 fast = head
5 while fast and fast.next:
6 slow = slow.next # advance one step at a time
7 fast = fast.next.next # advance two steps; fast outruns slow 2:1
8 return slowTime: O(n) โ both pointers traverse at most n nodes total.
Space: O(1) โ only two pointer variables regardless of list length.
Complexity Summary
| Approach | Time | Space | When to use |
|---|---|---|---|
| Slow and Fast Pointer | O(n) | O(1) | Any time you need the middle in a single pass |
Common Mistakes
- Checking only
fast.nextinstead offast and fast.next: On a list with an odd number of nodes, fast lands exactly on the last node. Accessingfast.next.nextwithout first verifyingfast.nextis not null causes a null pointer error. - Returning the first middle on even-length lists: If you stop the loop when
fast.next == null(instead offast == null || fast.next == null), slow ends up one step early, pointing to the first midpoint rather than the second. - Starting fast at
head.next: This shifts the ratio so slow arrives one node early, producing incorrect results for odd-length lists. - Two-pass counting: Traversing the whole list to get the length, then walking
length // 2steps in a second pass, works but is unnecessary complexity โ the slow/fast pointer solves it in one pass with no arithmetic. - Forgetting this technique is the key building block for other problems: Palindrome Linked List, Reorder List, and Rotate List all require finding the middle as their first step โ internalizing this pattern pays dividends.
Related Problems
reverse-linked-listโ fundamental pointer reversal that pairs with middle-finding in palindrome and reorder problemspalindrome-linked-listโ uses slow/fast to find the middle, then reverses the second half to comparereorder-listโ splits the list at the middle using this exact technique, then merges the two halvesremove-nth-node-from-end-of-listโ two-pointer trick applied to reach a node a fixed distance from the endodd-even-linked-listโ rearranges nodes by position using simultaneous pointer advances