Middle of the Linked List in Java: Count, Store, and the Slow-Fast Pointer Trick
-
Last Updated: November 7, 2026
-
By: javahandson
-
Series

Find the Middle of the Linked List in Java three ways: count and walk, store nodes, and the slow-fast pointer trick, each with a full dry run.
Middle of the Linked List in Java is a gentle warm-up, yet it teaches a trick you will reuse on many pointer problems. You are handed the head of a singly linked list. Your job is to return its middle node, nothing more.
The twist is tiny but worth noting. When the list has an odd count, there is one clear middle. When the count is even, there are two middles, and the rule here is to return the second one.
We will solve it in three steps, from plain to clever. First we count the nodes, then walk halfway again. Next we stuff every node into a list and index the middle. Last we use two pointers that move at different speeds.
Every approach gets a full, step-by-step dry run on the same seven-node list. No step is skipped, so you can watch each pointer move and see exactly why the middle comes out the way it does.
Let us pin down the rules before any code gets written.
Our running example is the list 10 -> 20 -> 30 -> 40 -> 50 -> 60 -> 70, which has seven nodes. The middle is the fourth node, the one holding 40. We will also trace a six-node list later to show how the even case picks the second middle.
A linked list is a chain of nodes. Every node stores a value and a next pointer that points to the node after it. The last node points to null, which marks the end of the chain.
The middle sits at index length / 2, using integer division. For seven nodes that is index 3, the fourth node. For six nodes that is also index 3, which is the second of the two middles.
The most direct idea has two passes. First you walk the whole list and count the nodes. Then you walk again, but stop after length / 2 hops, which lands you on the middle. It is simple and it always works.
count = 0
curr = head
while curr != null: // pass 1, count nodes
count = count + 1
curr = curr.next
mid = count / 2 // integer division
curr = head
for i from 0 to mid - 1: // pass 2, walk halfway
curr = curr.next
return currThis plan reads like two short walks over the same chain.
public class MiddleOfLinkedListCount {
public static ListNode middleNode(ListNode head) {
int count = 0;
ListNode curr = head;
while (curr != null) {
count++;
curr = curr.next;
}
int mid = count / 2;
curr = head;
for (int i = 0; i < mid; i++) {
curr = curr.next;
}
return curr;
}
}The Java version mirrors the plan line for line.
Let us trace the list 10 -> 20 -> 30 -> 40 -> 50 -> 60 -> 70. Pass one just counts, so watch count climb from 0 to 7 as curr visits each node.
| step | curr before move | count after ++ | curr after move |
|---|---|---|---|
| 0 | 10 | 1 | 20 |
| 1 | 20 | 2 | 30 |
| 2 | 30 | 3 | 40 |
| 3 | 40 | 4 | 50 |
| 4 | 50 | 5 | 60 |
| 5 | 60 | 6 | 70 |
| 6 | 70 | 7 | null (end) |
Pass one ends with count = 7. So mid = 7 / 2 = 3, meaning the middle is three hops from the head. Now pass two resets curr to the head and hops exactly three times.
| hop i | curr before hop | curr after hop |
|---|---|---|
| start | – | 10 (head) |
| 0 | 10 | 20 |
| 1 | 20 | 30 |
| 2 | 30 | 40 |
After three hops curr sits on 40, so the method returns the node holding 40. That is the correct middle of a seven-node list.
Let us walk both passes slowly and see why the numbers land where they do.
Pass one, counting the nodes.
Pass two, walking to the middle.
So curr rests on 40 after exactly three hops. The two passes together touch the list about one and a half times, which is the price of not being clever.
| 💡 Interview Insight A common opener is “how do you find the middle without knowing the length?”. Mention the count-and-walk idea first to show you understand it, then pivot to the two-pointer trick that skips the first pass entirely. |
The cost is already linear, which is good. Still, two separate passes feel wasteful, so the next ideas try to finish the job in a single walk.
Here is a one-pass idea that trades memory for simplicity. Walk the list once and drop every node into an ArrayList. An ArrayList gives you index access, so the middle is just the element at position size / 2.
nodes = empty list
curr = head
while curr != null: // one pass, collect nodes
nodes.add(curr)
curr = curr.next
return nodes.get(nodes.size() / 2)Think of it as copying the chain into a numbered shelf.
import java.util.*;
public class MiddleOfLinkedListStore {
public static ListNode middleNode(ListNode head) {
List<ListNode> nodes = new ArrayList<>();
ListNode curr = head;
while (curr != null) {
nodes.add(curr);
curr = curr.next;
}
return nodes.get(nodes.size() / 2);
}
}The code is short because the ArrayList does the heavy lifting.
Same list, 10 -> 20 -> 30 -> 40 -> 50 -> 60 -> 70. The single loop appends each node, so the list grows by one every step.
| step | node added | list contents (by value) | size |
|---|---|---|---|
| 0 | 10 | [10] | 1 |
| 1 | 20 | [10, 20] | 2 |
| 2 | 30 | [10, 20, 30] | 3 |
| 3 | 40 | [10, 20, 30, 40] | 4 |
| 4 | 50 | [10, 20, 30, 40, 50] | 5 |
| 5 | 60 | [10, 20, 30, 40, 50, 60] | 6 |
| 6 | 70 | [10, 20, 30, 40, 50, 60, 70] | 7 |
The loop stops when curr turns null, with size = 7. So the middle index is 7 / 2 = 3, and the element at index 3 is the node holding 40. The method returns that node.
Let us watch the list fill up, slot by slot.
Now the lookup is instant. We compute 7 / 2 = 3 and ask the list for index 3, which is 40. No second walk is needed, because the list remembers every position for us.
The catch is memory. We created seven extra references to hold the whole chain, so a million-node list would need a million slots. That is the price of random access on something that normally walks forward only.
| 💡 Interview Insight If you reach for an ArrayList, say out loud that it costs O(n) extra space. Interviewers like to hear that you know the trade, and it sets up the two-pointer answer as the memory-friendly upgrade. |
One pass is nice, but the extra memory stings. The final approach keeps the single pass and throws the extra memory away.
This is the trick interviewers hope to see. Run two pointers from the head. The slow one moves a single step each turn, while the fast one jumps two steps. When the fast pointer runs off the end, the slow pointer is sitting exactly on the middle.
The names slow and fast describe what they do, so we keep them instead of generic boundary names. People also call this the tortoise and hare pattern.
slow = head
fast = head
while fast != null and fast.next != null:
slow = slow.next // one step
fast = fast.next.next // two steps
return slowThe two speeds are the whole idea.
public class MiddleOfLinkedListTwoPointer {
public static ListNode middleNode(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
}The loop is tiny, so the condition is the part to understand.
Same seven-node list, 10 -> 20 -> 30 -> 40 -> 50 -> 60 -> 70. Both pointers start on 10. Each row shows the loop check, then where slow and fast land after the turn.
| iter | check: fast & fast.next | slow after +1 | fast after +2 |
|---|---|---|---|
| start | – | 10 | 10 |
| 1 | fast=10, fast.next=20 (ok) | 20 | 30 |
| 2 | fast=30, fast.next=40 (ok) | 30 | 50 |
| 3 | fast=50, fast.next=60 (ok) | 40 | 70 |
| stop | fast=70, fast.next=null | 40 | 70 |
The loop stops at iteration 3 because fast is on 70 and fast.next is null, so the double hop is not allowed. At that moment slow is on 40, which is the middle. The method returns the node holding 40, matching the first two approaches.
Now the even case, a six-node list 10 -> 20 -> 30 -> 40 -> 50 -> 60. This shows how the fast pointer running clean off the end gives us the second middle.
| iter | check: fast & fast.next | slow after +1 | fast after +2 |
|---|---|---|---|
| start | – | 10 | 10 |
| 1 | fast=10, fast.next=20 (ok) | 20 | 30 |
| 2 | fast=30, fast.next=40 (ok) | 30 | 50 |
| 3 | fast=50, fast.next=60 (ok) | 40 | null |
| stop | fast=null | 40 | null |
Here fast lands on null after the third turn, so the loop ends. Slow is on 40, which is the second of the two middle nodes, 30 and 40. That is exactly what the problem asks for.
Let us follow both pointers turn by turn and see why slow always ends up in the middle.
The odd list, seven nodes.
The even list, six nodes.
The pattern is steady. Fast travels two nodes for every one that slow travels, so by the time fast exhausts the list, slow has covered half of it. One single pass, and no extra memory, which is why this answer wins.
| 💡 Interview Insight Interviewers often ask why the loop checks both fast and fast.next. Explain that fast.next.next would crash with a null pointer if either is missing, so the two-part guard keeps the double hop safe on both odd and even lists. |
| Approach | Passes over list | Extra memory | Feel |
|---|---|---|---|
| Count and walk | About 1.5 | A counter only | Simple, two walks |
| Store in list | One | A list of all nodes | Easy, memory heavy |
| Slow and fast | One | Two pointers | Lean and quick |
All three return the same middle node. They just pay different prices to get there.
| Approach | Time | Space | Note |
|---|---|---|---|
| Count the length, then walk | O(n) | O(1) | Two passes, but no extra memory |
| Store the nodes in a list | O(n) | O(n) | One pass, heavy on memory |
| Slow and fast pointers | O(n) | O(1) | One pass, tiny memory, expected answer |
Every version is linear in time, so the real contest is memory and elegance. The store-in-list idea is the easiest to picture, yet it copies the whole chain. The slow and fast pointers finish in one pass with only two variables, which is why it is the answer worth memorizing.
In an interview, you can mention the count-and-walk idea to show the straightforward path. Then describe the list trick as a one-pass option. Finally land on the two pointers as the clean, memory-light solution, and explain the loop guard.
| 💡 Interview Insight If asked to prove the two-pointer middle is correct, keep it short. Fast moves at double speed, so when it has traveled the full list, slow has traveled exactly half, which is the middle by definition. |
A few small slips catch beginners on this problem. Keep them in view.
Run a one-node list and a two-node list through your code before calling it done. Those tiny cases expose off-by-one errors faster than any long list will.
A: Use two pointers from the head. Move a slow pointer one node at a time and a fast pointer two nodes at a time. When the fast pointer reaches the end, the slow pointer sits on the middle node. This runs in one pass with O(1) extra memory.
A: The fast pointer jumps with fast.next.next, so both fast and fast.next must exist first. Checking fast != null && fast.next != null in that order stops a null pointer crash on both odd and even length lists.
A: The second middle. With two pointers, the fast pointer lands on null after the final double hop, which leaves the slow pointer on the second of the two central nodes. That matches the LeetCode rule.
A: Yes. Count the nodes in one pass, then walk length/2 steps in a second pass. You can also store every node in an ArrayList and read index size/2. Both work in O(n) time, but the two-pointer method avoids a second pass and extra memory.
A: All three approaches are O(n) in time. Count-and-walk and slow-fast use O(1) extra space, while storing nodes in a list uses O(n) space. The slow-fast pointer approach is the expected interview answer because it is one pass and memory-light.
Middle of the Linked List in Java looks small, yet it hides a pattern you will lean on again and again. Once you see that two pointers at different speeds can measure a list, many linked list problems start to feel familiar.
Our seven-node traces made the payoff clear. Counting then walking worked but took one and a half passes. Storing the nodes finished in one pass but copied the whole chain. The slow and fast pointers did it in one pass with almost no memory.
So take the pattern, not just the answer. When you need a position inside a list without knowing its length, send a fast pointer ahead and let a slow pointer trail at half speed.
That tortoise and hare habit powers cycle detection, nth-from-end, and more. It will serve you well on the harder linked list problems still ahead.