Algorithm

Middle of the Linked List

Two Pointer Pattern

Middle of the Linked List

Given the head of a singly linked list, return the middle node of the linked list. If there are two middle nodes, return the second middle node.

CONSTRAINTS
  • The number of nodes in the list is in the range [1, 100]
  • 1 <= Node.val <= 100
  • Solve in a single pass
EXAMPLE 1
Input: head = [1,2,3,4,5]
Output: [3,4,5]
Five nodes, so the single middle node is the third one. Returning a node in a linked list means returning it together with everything after it, hence [3,4,5].
EXAMPLE 2
Input: head = [1,2,3,4,5,6]
Output: [4,5,6]
Six nodes means there are two middle nodes, node 3 and node 4. The rule says return the second one, node 4, along with the rest of the list.
EXAMPLE 3
Input: head = [1]
Output: [1]
A single node is its own middle, so it is returned unchanged.
Do I return the middle node itself, or its value or index?
Return the node. Since this is a linked list, returning a node hands back that node plus everything chained after it — you cannot return it in isolation.
An even-length list has two middle nodes — which one do I return?
The second of the two. For [1,2,3,4,5,6] that is node 4, not node 3. Worth confirming with the interviewer, since a common variant asks for the first middle instead.
Can the list be empty?
No — the constraints guarantee at least one node, so you never have to return null. The smallest input is a single node, which is its own middle.

We have a singly linked list, and our goal is to find its exact middle node. But there is a catch: unlike an array where we can instantly check the length and jump to the middle element in a split second, a linked list is a blind chain. We cannot query its size or jump to an arbitrary index without physically walking the nodes one by one. How do we locate the center of a structure when we don't know how long it actually is?

The Double-Pass Tax

The most straightforward approach is to solve this in two separate trips. First, we traverse the entire list from head to tail to count how many nodes exist. Once we have the total length, we calculate the midpoint index. Then, we reset our pointer to the start and take a second trip, walking exactly halfway through the list to arrive at the middle node.

While this successfully finds the center, it forces us to read the list twice. It works, but making two full trips is highly inefficient.

python
# Trip 1: Count the nodes
length = 0
curr = head
while curr:
    length += 1
    curr = curr.next

# Trip 2: Walk to the middle
mid_index = length // 2
curr = head
for _ in range(mid_index):
    curr = curr.next

return curr
The Jogger & The Sprinter

To find the middle in a single pass, we introduce two distinct pointers that traverse the list simultaneously. Each pointer has a strict contract:
- The Slow Pointer (slow): Acts as our steady jogger. It advances exactly one node at a time.
- The Fast Pointer (fast): Acts as our sprinter. It surges forward exactly two nodes at a time.

Both pointers start side-by-side at the head of the list.

The 2:1 Velocity Symmetry

The reason this configuration works comes down to a simple mathematical distance relationship. Because the fast pointer moves exactly twice as fast as the slow pointer, the total distance covered by fast will always be exactly double the distance covered by slow.

Therefore, when fast reaches the absolute end of the list (distance D), slow must have traveled exactly half that distance (D/2). Without ever counting the total number of nodes, the steady runner is naturally guided to the exact center.

Synchronized Strides

At each step, we first verify that the fast pointer has a valid next step to take, ensuring we do not encounter a null pointer exception. If it is safe to proceed, we advance both pointers in unison: we move slow forward by one link, and fast forward by two links.

python
slow = head
fast = head

# Sprint and jog in unison until fast reaches the end
while fast and fast.next:
    slow = slow.next       # Advance 1 step
    fast = fast.next.next  # Advance 2 steps

# slow is now sitting perfectly at the midpoint
return slow
Odd Spans and Lone Nodes

The movement rules naturally handle different list structures without any extra branching logic:
- Odd-length list (e.g., 5 nodes): fast lands exactly on the tail node (Node 5). Since fast.next is null, the loop terminates. slow sits perfectly on Node 3 (the exact middle).
- Even-length list (e.g., 6 nodes): fast sprints past the tail and lands on null. The loop terminates. slow sits on Node 4, which is the second of the two middle nodes, perfectly matching the problem's criteria.
- Single-node list (1 node): From the very start, fast.next is null. The loop never executes, and slow (still pointing to head) is immediately returned.

Worked Example:Finding the Center
1
slowfast
2
3
4
5
NULL
We start with both 'slow' (jogger) and 'fast' (sprinter) pointers at the head node containing 1.
1
2
slow
3
fast
4
5
NULL
We advance pointers in unison: 'slow' moves one step to 2, and 'fast' moves two steps to 3.
1
2
3
slow
4
5
fast
NULL
We advance again: 'slow' moves one step to 3, and 'fast' moves two steps to the tail node 5.
1
2
3
slow
4
5
NULL
Since fast's next node is null, we terminate the traversal. 'slow' is resting at node 3, the exact center of our list.
Interactive Strategy Visualization
TORTOISE & HARE ENGINE

Linear Discovery via 2-Pointer Speeds

1Slow (1x)Fast (2x)2345

Current Progress

Phase 1: Initialization

Both Slow and Fast pointers start at the head. In this race, the speeds are intentionally uneven to find the balance point.

Mathematical Core

If Pointer A moves @ speed 1 and Pointer B moves @ speed 2, when B hits the end ($L$), A will be at $L/2$. No counting nodes required!

Efficiency Strategy: One Pass Discovery

Traditional solutions use two passes (count then find). This method finds the middle in exactly one pass.

O(N) Time Two Passes
O(N) Time · O(1) Space Single Pass