Middle of the Linked List in Java: Count, Store, and the Slow-Fast Pointer Trick

  • Last Updated: November 7, 2026
  • By: javahandson
  • Series
img

Middle of the Linked List in Java: Count, Store, and the Slow-Fast Pointer Trick

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.

1. Introduction

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.

2. Understanding the Problem

Let us pin down the rules before any code gets written.

  • You get only the head node of a singly linked list, so you start at the front.
  • Each node holds a value and a link to the next node, nothing else.
  • Return the middle node itself, not just its value.
  • For an even-length list, two nodes sit in the middle, and you return the second one.

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.

3. Concepts You Need Here

3.1 A Linked List Only Walks Forward

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.

  • You hold only the head, so every journey starts at the front.
  • There is no index and no size field, unlike an array.
  • To reach any node, you must hop from next to next until you arrive.

3.2 Finding the Middle Means Counting Steps

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.

  • One way counts the length first, then walks half of it.
  • Another way keeps every node in a list, then grabs the middle index.
  • The slickest way runs two pointers at once, so one pass is enough.

4. Approach 1: Count the Length, Then Walk Again

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.

4.1 Pseudocode

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 curr

4.2 Pseudocode Explained

This plan reads like two short walks over the same chain.

  • Pass one starts at the head and moves node by node, adding one to count each time, until it falls off the end at null.
  • Next we compute mid as count / 2, which is the number of hops that reach the middle.
  • Pass two starts fresh at the head and hops exactly mid times.
  • Finally curr is sitting on the middle node, so we return it.

4.3 Java Code

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;
    }
}

4.4 Java Code Explained

The Java version mirrors the plan line for line.

  • Lines 4 and 5 set count to 0 and point curr at the head, ready for the first walk.
  • Lines 6 to 9 are the counting loop. It keeps moving curr forward and bumping count until curr becomes null.
  • Line 10 works out mid as count / 2, since Java divides two ints by throwing away the remainder.
  • Then line 11 resets curr back to the head for the second walk.
  • Lines 12 to 14 hop mid times, so curr climbs from the head to the middle.
  • Line 15 returns curr, which now rests on the middle node.

4.5 Dry Run of the Count-and-Walk Approach

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.

stepcurr before movecount after ++curr after move
010120
120230
230340
340450
450560
560670
6707null (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 icurr before hopcurr after hop
start–10 (head)
01020
12030
23040

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.

4.6 Reading the Dry Run

Let us walk both passes slowly and see why the numbers land where they do.

Pass one, counting the nodes.

  • At step 0 curr starts on 10, count rises to 1, and curr steps to 20.
  • Through steps 1 and 2, curr moves onto 20 then 30, pushing count to 2 and then 3.
  • By step 3 curr reaches 40, the real middle, but the loop cannot know that yet, so count becomes 4 and it keeps going.
  • During steps 4, 5, and 6, curr passes 50, 60, and 70, lifting count to 7.
  • After 70 the next pointer is null, so the loop stops and the final count is 7.

Pass two, walking to the middle.

  • We reset curr to the head, 10, and compute mid = 3.
  • Hop 0 moves curr from 10 to 20, which is one node in.
  • Then hop 1 moves it from 20 to 30, the halfway warm-up.
  • Finally hop 2 moves it from 30 to 40, and the loop ends because i has reached mid.

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.

4.7 Time and Space Cost

  • Time is O(n), because we walk the list roughly one and a half times, and constants drop out.
  • Space is O(1), since we only keep a counter and a pointer.

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.

5. Approach 2: Store the Nodes in a List

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.

5.1 Pseudocode

nodes = empty list
curr = head
while curr != null:        // one pass, collect nodes
    nodes.add(curr)
    curr = curr.next
 
return nodes.get(nodes.size() / 2)

5.2 Pseudocode Explained

Think of it as copying the chain into a numbered shelf.

  • We start curr at the head and move it forward one node at a time.
  • Each node gets added to the list, so the list ends up holding every node in order.
  • Because a list knows its own size, we grab size / 2 directly.
  • That index is the middle, so we return the node parked there.

5.3 Java Code

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);
    }
}

5.4 Java Code Explained

The code is short because the ArrayList does the heavy lifting.

  • Line 6 makes an empty ArrayList that will hold node references, not copies.
  • Line 7 points curr at the head so the walk can begin.
  • Lines 8 to 11 are the collecting loop. Each turn adds the current node and then steps forward.
  • Line 12 reads the size, divides by two, and returns the node at that index in one go.

5.5 Dry Run of the Store-in-List Approach

Same list, 10 -> 20 -> 30 -> 40 -> 50 -> 60 -> 70. The single loop appends each node, so the list grows by one every step.

stepnode addedlist contents (by value)size
010[10]1
120[10, 20]2
230[10, 20, 30]3
340[10, 20, 30, 40]4
450[10, 20, 30, 40, 50]5
560[10, 20, 30, 40, 50, 60]6
670[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.

5.6 Reading the Dry Run

Let us watch the list fill up, slot by slot.

  • At step 0 the node 10 lands at index 0, so the list is [10] and size is 1.
  • Through steps 1 and 2, nodes 20 and 30 join, growing the list to [10, 20, 30].
  • By step 3 the node 40 takes index 3, which is exactly where we will look later.
  • During steps 4, 5, and 6, nodes 50, 60, and 70 fill the rest, ending at size 7.

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.

5.7 Time and Space Cost

  • Time is O(n), since we walk the list once and the index lookup is instant.
  • Space is O(n), because the list holds a reference to every node.

One pass is nice, but the extra memory stings. The final approach keeps the single pass and throws the extra memory away.

6. Approach 3: Slow and Fast Pointers

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.

6.1 Pseudocode

slow = head
fast = head
while fast != null and fast.next != null:
    slow = slow.next          // one step
    fast = fast.next.next     // two steps
 
return slow

6.2 Pseudocode Explained

The two speeds are the whole idea.

  • Both pointers begin on the head node.
  • The loop runs only while fast and fast.next are both real, which guards the double hop from hitting null.
  • On every turn slow advances one node and fast advances two.
  • Since fast covers the list twice as quickly, slow has gone halfway when fast finishes, so we return slow.

6.3 Java Code

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;
    }
}

6.4 Java Code Explained

The loop is tiny, so the condition is the part to understand.

  • Lines 4 and 5 place both slow and fast on the head.
  • Line 6 checks fast != null && fast.next != null, which makes sure the next two hops exist before we take them.
  • Line 7 moves slow forward by one node.
  • Then line 8 moves fast forward by two nodes using fast.next.next.
  • Line 10 returns slow once the loop ends, and slow is now on the middle.

6.5 Dry Run of the Slow and Fast Pointers

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.

itercheck: fast & fast.nextslow after +1fast after +2
start–1010
1fast=10, fast.next=20 (ok)2030
2fast=30, fast.next=40 (ok)3050
3fast=50, fast.next=60 (ok)4070
stopfast=70, fast.next=null4070

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.

itercheck: fast & fast.nextslow after +1fast after +2
start–1010
1fast=10, fast.next=20 (ok)2030
2fast=30, fast.next=40 (ok)3050
3fast=50, fast.next=60 (ok)40null
stopfast=null40null

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.

6.6 Reading the Dry Run

Let us follow both pointers turn by turn and see why slow always ends up in the middle.

The odd list, seven nodes.

  • At the start both pointers rest on 10, so no ground is covered yet.
  • On iteration 1 the check passes, slow steps to 20, and fast leaps to 30.
  • Through iteration 2, slow moves to 30 while fast jumps to 50, staying twice as far along.
  • By iteration 3 slow reaches 40 and fast reaches 70, the last node.
  • Now fast.next is null, so the loop stops and slow is parked on 40, the true middle.

The even list, six nodes.

  • Again both pointers begin on 10 with nothing covered.
  • Iteration 1 sends slow to 20 and fast to 30, same as before.
  • During iteration 2, slow lands on 30 and fast lands on 50.
  • On iteration 3 slow steps to 40, but fast jumps past the end to null.
  • Because fast is null, the loop stops, leaving slow on 40, the second middle.

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.

6.7 Comparing the Three Traces

ApproachPasses over listExtra memoryFeel
Count and walkAbout 1.5A counter onlySimple, two walks
Store in listOneA list of all nodesEasy, memory heavy
Slow and fastOneTwo pointersLean and quick

7. Comparing the Three Approaches

All three return the same middle node. They just pay different prices to get there.

ApproachTimeSpaceNote
Count the length, then walkO(n)O(1)Two passes, but no extra memory
Store the nodes in a listO(n)O(n)One pass, heavy on memory
Slow and fast pointersO(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.

8. Common Mistakes and Edge Cases

A few small slips catch beginners on this problem. Keep them in view.

  • Writing the loop as while (fast.next != null) alone, which crashes on an even list when fast becomes null.
  • Checking fast.next before fast, since the order matters and the null check on fast must come first.
  • Returning slow.val when the problem asks for the node itself, not the value inside it.
  • Forgetting that an even list should return the second middle, not the first.
  • Assuming a single node has no middle, when in fact the head is its own middle.

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.

9. FAQ’s on Middle of the Linked List in Java

Q: How do you find the middle of a linked list in Java?

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.

Q: Why does the loop check both fast and fast.next?

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.

Q: For an even-length linked list, which middle is returned?

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.

Q: Can you find the middle without the slow-fast trick?

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.

Q: What is the time and space complexity?

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.

10. Conclusion

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.

11. Further Reading

Leave a Comment