You are given the head of a singly linked list. Delete the middle node of the list and return the head of the modified list.
For a list of size n, the middle node is the node at index ⌊n / 2⌋ using 0-based indexing — where ⌊x⌋ is the largest integer less than or equal to x.
Concretely, for n = 1, 2, 3, 4, 5 the middle indices are 0, 1, 1, 2, 2. So in a list of 7 nodes the middle is index 3; in a list of 4 nodes it is index 2.
Deleting the only node of a single-element list leaves an empty list, so you return an empty (null) head.
fast two steps and slow one step per loop, trailing slow with a prev pointer; when fast falls off the end, set prev.next = slow.next.fast moves twice as far as slow. When fast has traveled the whole list of length n, slow has traveled n/2 — precisely index ⌊n/2⌋.prev.next past it. In languages with manual memory you may also free it; the judge only checks the resulting sequence of values.fast a k-step head start, then advance both until fast hits the end — slow lands on the target node's predecessor.fast ever meets slow, there is a loop. This is Floyd's cycle-detection algorithm.Input: head = [1,3,4,7,1,2,6] Output: [1,3,4,1,2,6] n = 7, so the middle is index ⌊7/2⌋ = 3 (value 7). Removing it leaves [1,3,4,1,2,6].
Input: head = [1,2,3,4] Output: [1,2,4] n = 4, so the middle is index ⌊4/2⌋ = 2 (value 3).
Input: head = [2,1] Output: [2] n = 2, so the middle is index ⌊2/2⌋ = 1 (value 1). Only node 0 remains.
- The number of nodes in the list is in the range [1, 10^5]. - 1 <= Node.val <= 10^5
Deleting the middle node looks trivial once you know where the middle is — the real skill is finding it in a single pass, without ever counting the list twice. This is your first taste of the fast-and-slow pointer trick that powers half of all linked-list interview questions.
null.next past it.A minute of questions before you code shows you reason about guarantees and edge cases the way a senior engineer does.
“Is the list guaranteed to be non-empty?”
The constraints promise at least one node, so I never receive a null head — but I still guard it defensively.
“What should I return if the list has exactly one node?”
Its middle is index 0, so deleting it leaves an empty list and I return null.
“How large can the list get?”
Up to 10^5 nodes, so an O(n) pass is fine — but I would rather not traverse the whole list twice if one pass suffices.
Before I code, let me confirm a couple of things.
The middle is floor of n over 2 with 0-based indexing, correct?
And a single-node list should come back empty, since its middle is the only node?
Plain English: find the node at index ⌊n/2⌋, unlink it by connecting its predecessor to its successor, and return the head.
Worked example — head = [1,3,4,7,1,2,6]
index: 0 1 2 3 4 5 6
list: 1 → 3 → 4 → 7 → 1 → 2 → 6 n = 7, middle = ⌊7/2⌋ = 3
remove index 3 (value 7):
1 → 3 → 4 ──────→ 1 → 2 → 6
result: 1 → 3 → 4 → 1 → 2 → 6
In a singly linked list you can only detach a node through its predecessor. To delete index mid, keep a prev pointer trailing one step behind the middle, then set prev.next = prev.next.next.
Move fast two nodes for every one node slow moves. fast covers twice the distance, so when fast falls off the end, slow sits at ⌊n/2⌋ — the middle — with no counting required.
step slow fast 0 0 0 1 1 2 2 2 4 3 3 6 fast.next is null → stop, slow = 3 = middle
If head.next is null there is nothing after the head, its middle is index 0, and the answer is an empty list. Guard this up front and the main loop stays clean.
| Two pass (count then walk) | Fast & slow (one pass) | |
|---|---|---|
| Passes over list | 2 | 1 |
| Time | O(n) | O(n) |
| Space | O(1) | O(1) |
Both are linear, but the two-pointer method finds the middle in a single sweep — the version you want to reach for. See the full code in the Approaches selector below.
Key takeaway
To find the middle of a linked list in one pass, run a fast pointer at double speed; when it reaches the end, a slow pointer is at the middle. Keep a prev pointer trailing the slow pointer so you can unlink cleanly.
if head has no next: return null
slow = head, fast = head, prev = null
while fast and fast.next:
prev = slow
slow = slow.next
fast = fast.next.next
prev.next = slow.next
return head