Given the head of a singly linked list, return the middle node of the list.
If the list has an even number of nodes, there are two middle nodes — return the second of the two.
You are handed the head pointer; return the node where the middle begins. Everything from that node to the end is your answer.
fast. By the time fast has covered the full length, slow has covered exactly half — the midpoint.fast and fast.next exist. On even lengths fast overshoots to null and slow lands one node past center — the second middle.fast ever meets slow, there's a cycle. It's called Floyd's cycle detection — this problem is the gentle introduction to it.n steps first, then move both together until the leader hits the end — the trailer is now at the node to remove.Input: head = [1,2,3,4,5] Output: [3,4,5] The list has 5 nodes, so the single middle is node 3.
Input: head = [1,2,3,4,5,6] Output: [4,5,6] The list has 6 nodes, so the two middles are 3 and 4 — we return the second one, node 4.
- The number of nodes in the list is in the range [1, 100]. - 1 <= Node.val <= 100
Finding the middle of a linked list looks trivial — until you remember you can't index into it. There's no list[n/2]; you can only walk forward one node at a time. This problem is the gateway to the two-pointer family, and the trick you learn here reappears everywhere.
node = node.next until you hit null.floor(n / 2) (0-based), which lands on the second middle when n is even.In plain words: return the node sitting at position floor(n / 2) counting from 0, where n is the number of nodes. Formally, if the nodes are v[0], v[1], …, v[n-1], return the node v[floor(n/2)] — and because the answer is a node, everything chained after it comes along automatically.
Worked example — head = [1,2,3,4,5,6]
index: 0 1 2 3 4 5 node: 1 → 2 → 3 → 4 → 5 → 6 → null n = 6, middle index = 6/2 = 3 answer starts at node 4 → [4,5,6]
Asking one or two sharp questions before coding shows you thought about the shape of the input, not just the happy path.
“Is the list guaranteed to be non-empty?”
The constraints promise at least one node, so we never return null — but confirming it means we can skip an empty-list guard.
“For an even-length list, which of the two middles do we return?”
The second one — this single rule decides whether our pointer math lands one node early or exactly right.
“How large can the list get?”
Up to 100 nodes here, so even a two-pass scan is instant — but the one-pass idea generalizes to huge lists and streams.
Before I start, I have two quick clarifying questions.
First — can I assume the list always has at least one node?
And for an even number of nodes, I return the second of the two middles, correct?
Count the nodes and the answer is the node at 0-based index floor(n / 2). For n = 5 that's index 2 (node 3); for n = 6 it's index 3 (node 4 — the second middle). This already gives a correct two-pass solution: count, then walk floor(n/2) steps.
Run a slow pointer one step at a time and a fast pointer two steps at a time from the same start. When fast runs off the end, slow has covered exactly half the distance — it is standing on the middle. One pass, no length needed.
slow: 1 → 2 → 3 fast: 1 → 3 → 5 → (off the end) slow stops at 3 ✓
Stop while fast and fast.next both exist. For odd n, fast lands on the last node and the loop ends with slow on the single middle. For even n, fast steps past the end to null and slow lands on the second middle — exactly the tie-break we wanted, with no special case.
| Two-pass count | Fast & slow pointers | |
|---|---|---|
| Time | O(n) | O(n) |
| Space | O(1) | O(1) |
| Passes over the list | 2 | 1 |
| Needs the length first |
Both are linear, but the fast-and-slow version reads the list a single time and never stores the count — the template you'll reuse for cycle detection and nth-from-end. The full code for each is in the Approaches selector below.
Key takeaway
Two pointers at different speeds turn a "where's the middle?" question into a single walk: move slow by one and fast by two, and when fast falls off the end, slow is standing on the middle. This tortoise-and-hare pattern is the backbone of many linked-list problems.
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow