Linked List · 15 of 36
Find the middle Element of a linked list
Find the box in the middle of a chain in one walk, by sending one runner twice as fast as the other.
- Simple way
- time O(n)
room O(1) - Clever way
- time O(n)
room O(1)
The problem, simply
You get the head of a linked list. Give back the middle box.
If the list has an odd number of boxes, there is one middle. If it has an even number, there are two middle boxes, and the usual rule (LeetCode 876 and GeeksforGeeks) is to return the second one. So for 1 2 3 4 5 6 the answer is 4.
A story to remember it
Picture it
Five boxes. Two on each side of box 3, so box 3 is the middle.
- answer
Six boxes. Both 3 and 4 sit in the middle. The rule says return the second one, 4.
- checking
- answer
Examples
Odd length
- In
1 -> 2 -> 3 -> 4 -> 5- Out
3
Two boxes before and two after.
Even length
- In
1 -> 2 -> 3 -> 4 -> 5 -> 6- Out
4
Two middles, 3 and 4. We return the second one.
Two boxes
- In
1 -> 2- Out
2
Both are middles. The second one wins.
One box
- In
7- Out
7
The only box is the middle.
Way 1: the simple way
Count first, then walk.
- Walk the whole list and count the boxes,
n. - Start again at the head and take
n / 2steps (whole number division). - The box you stand on is the middle. For
n = 6that is 3 steps, landing on 4. Forn = 5it is 2 steps, landing on 3.
First walk: count 6 boxes. Second walk: 6 / 2 = 3 steps from the head lands on 4.
- n
- 6
- steps
- 3
- seen
- answer
class Solution {
public ListNode middleNode(ListNode head) {
int n = 0;
for (ListNode p = head; p != null; p = p.next) n++; // count the boxes
ListNode curr = head;
for (int i = 0; i < n / 2; i++) curr = curr.next; // walk half way
return curr;
}
}How long it takes: one full walk plus half a walk, O(n). Extra room: a counter, O(1). Correct, but it reads the list one and a half times, and some versions of the question say "in one pass".
Way 2: the clever way
Send the kid and the puppy. slow moves one box, fast moves two boxes. When fast cannot take two more steps, slow is at the middle.
- Put
slowandfaston the head. - While
fastis notnullandfast.nextis notnull: moveslowone step andfasttwo steps. - Return
slow.
The puppy runs to the wall, the kid stops at the middle
01 / 06
Both start on the head, box 1.
- steps
- 0
- looking now
- seen
- answer
- path
class Solution {
public ListNode middleNode(ListNode head) {
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next; // the kid takes one step
fast = fast.next.next; // the puppy takes two
}
return slow; // the puppy hit the wall, the kid is half way
}
}How long it takes: fast crosses the list once, so about n / 2 loop turns, O(n). Extra room: two pointers, O(1). It is one pass, which matters when the list is a stream you can only read once.
Watch out for
- An empty list.
headisnull, the loop never runs and you returnnull, which is fine. - Checking only
fast.next != null. Whenfastitself isnullthat crashes. Checkfastfirst. - Moving
fastbefore checking. Always check bothfastandfast.nextright before the two step jump.
What interviewers ask next
- Return the first middle instead. Change the loop condition as in the trap above, or start
fastathead.next. - Delete the middle node (LeetCode 2095). Keep a
prevpointer one box behindslow, then setprev.next = slow.next. - Is the list a palindrome? Find the middle, reverse the second half, compare the two halves, then reverse it back.
- Split a list into two halves for merge sort. Find the first middle, then cut after it.
- Does the list have a loop? The same two runners: if they ever land on the same box, there is a loop.
Remember this
Grown-up words: the kid and the puppy are the slow and fast pointers, also called the tortoise and hare technique, and walking the list once is a single pass.