Editorial
Core insight
Delete the Middle Node of a Linked List · Two Pointers
Core Insight for Delete the Middle Node of a Linked List
The core insight is to use two pointers moving at different speeds to simulate finding the middle without knowing the length n beforehand.
If we have a Slow Pointer moving 1 step at a time and a Fast Pointer moving 2 steps at a time, the Fast Pointer covers distance at twice the rate of the Slow Pointer.
- When the Fast Pointer reaches the end of the list (index
n), the Slow Pointer will be exactly at the middle (indexn/2). - Invariant: The distance covered by
fastis always the distance covered byslow.
The Deletion Constraint: To delete a node in a singly linked list, we require access to its predecessor (the node immediately before it). If the Slow Pointer lands directly on the middle node, we cannot easily delete it because we don't have a reference to the previous node.
To solve this, we can modify the initialization. Instead of starting both pointers at head, we can look ahead. Alternatively, we can track a previous pointer. The most elegant modification for this specific problem is to ensure the slow pointer stops one node before the middle. We achieve this by letting the fast pointer lead significantly or by skipping the first step for the slow pointer relative to the fast pointer's check.
Visual Description:
Imagine the list as a linear track. We initialize slow at the head and fast two steps ahead (or check two steps ahead). As the algorithm progresses, the fast pointer rapidly approaches the null terminator. The moment fast (or fast.next) hits null, the slow pointer is positioned exactly at the node prior to the one we need to delete. This allows us to perform slow.next = slow.next.next immediately.

Deep dive
Full breakdown
Full reasoning, pitfalls, and implementation flow
LeetCode 2095: Delete the Middle Node of a Linked List Solution & Explanation
Problem Overview
TL;DR: Use the Two Pointer technique (Fast and Slow) to traverse the list in a single pass, locating the node immediately preceding the middle node to adjust its next pointer.
You are given the head of a linked list and tasked with deleting the middle node. The problem defines the middle node based on the size n of the list: it is the ⌊n / 2⌋-th node (using 0-based indexing). After removing the node, return the head of the modified list.
This is a popular interview question, often referred to as LeetCode 2095, that tests your ability to manipulate pointers efficiently without using extra space or multiple passes.
Brute Force Approach for Delete the Middle Node of a Linked List
The naive approach relies on a two-pass strategy. Since we cannot determine the middle index without knowing the total length of the list, we must first count the nodes.
- First Pass: Traverse the entire linked list to calculate the total length
n. - Calculate Index: Determine the index of the node to delete:
target = floor(n / 2). - Second Pass: Traverse the list again from the
head, stopping at the node just before the target index (target - 1). - Delete: Update the
nextpointer of the predecessor node to skip the middle node.
Pseudo-code:
length = 0
current = head
while current is not null:
length++
current = current.next
target_index = length / 2
current = head
for i from 0 to target_index - 1:
current = current.next
current.next = current.next.next
return headComplexity Analysis:
- Time Complexity: . While technically linear, this requires traversing the list twice.
- Space Complexity: .
- Why it is suboptimal: In strict system constraints or very large distributed lists, minimizing passes is crucial for performance. The brute force solution works but demonstrates a lack of familiarity with pointer arithmetic patterns.
Algorithm Strategy: Two Pointer Patterns
- Edge Case Handling: If the list has only one node (
head.nextis null), the middle node is the head itself. We returnnull(or the equivalent empty list). - Pointer Initialization:
- Initialize
slowtohead. - Initialize
fasttohead.next.next. This "head start" for the fast pointer effectively shifts the final position of theslowpointer backward by one, landing it on the predecessor of the middle node rather than the middle node itself.
- Initialize
- Traversal:
- Loop while
fastis not null andfast.nextis not null. - In each iteration, move
slowforward by 1 node. - Move
fastforward by 2 nodes.
- Loop while
- Deletion:
- Once the loop terminates,
slowpoints to the node before the middle. - Update
slow.nextto point toslow.next.next, effectively unlinking the middle node.
- Once the loop terminates,
- Return: Return the original
head.
Execution Flow
Consider the input head = [1, 3, 4, 7, 1, 2, 6]. Length is 7. Middle node is 7 (index 3).
- Check Edge Case: List size is > 1. Proceed.
- Init:
slowpoints to1(Index 0).fastpoints to4(Index 2).
- Iteration 1:
fast(Index 2) andfast.next(Index 3) are valid.slowmoves to3(Index 1).fastmoves to1(Index 4).
- Iteration 2:
fast(Index 4) andfast.next(Index 5) are valid.slowmoves to4(Index 2).fastmoves to6(Index 6).
- Iteration 3:
fastis at Index 6.fast.nextisnull. Loop terminates.
- Deletion:
slowis at node4(Index 2). The middle node is7(Index 3).- Execute
slow.next = slow.next.next. - Node
4now points to1(Index 4), skipping7.
- Result:
[1, 3, 4, 1, 2, 6].
Proof of Correctness
The correctness relies on the arithmetic series of the pointers. Let be the number of nodes.
The fast pointer moves 2 steps for every 1 step of slow.
Normally, slow travels steps when fast travels steps.
By initializing fast at index 2 (conceptually head.next.next), we effectively simulate a race where fast has already traveled 2 units.
When fast reaches the end (), slow has traveled .
Index is exactly the predecessor of the middle node . This logic holds for both odd and even lengths due to integer division behavior.
Pattern Reuse Notes
The Two Pointer pattern used here is fundamental for linked list problems. Similar logic applies to:
- LeetCode 19: Remove Nth Node From End of List - Uses a fixed gap (separation) between pointers to find a relative position from the end.
- LeetCode 876: Middle of the Linked List - Uses the exact same Fast/Slow logic, but returns the middle node instead of deleting it.
Feynman coach · Before you peek at the code
Can you explain the core insight in your own words?
If you can explain it before reading code, you’re far more likely to recall it under interview pressure.
Reference Implementation
C++ Solution for LeetCode 2095
1/**
2 * Definition for singly-linked list.
3 * struct ListNode {
4 * int val;
5 * ListNode *next;
6 * ListNode() : val(0), next(nullptr) {}
7 * ListNode(int x) : val(x), next(nullptr) {}
8 * ListNode(int x, ListNode *next) : val(x), next(next) {}
9 * };
10 */
11class Solution {
12public:
13 ListNode* deleteMiddle(ListNode* head) {
14 // Edge case: If list has only 1 node, return nullptr
15 if (head == nullptr || head->next == nullptr) {
16 return nullptr;
17 }
18
19 ListNode* slow = head;
20 // Start fast two steps ahead to ensure slow stops at the predecessor
21 ListNode* fast = head->next->next;
22
23 while (fast != nullptr && fast->next != nullptr) {
24 slow = slow->next;
25 fast = fast->next->next;
26 }
27
28 // Delete the middle node
29 ListNode* toDelete = slow->next;
30 slow->next = slow->next->next;
31 delete toDelete; // Optional: Free memory in C++
32
33 return head;
34 }
35};Java Solution for LeetCode 2095
1/**
2 * Definition for singly-linked list.
3 * public class ListNode {
4 * int val;
5 * ListNode next;
6 * ListNode() {}
7 * ListNode(int val) { this.val = val; }
8 * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
9 * }
10 */
11class Solution {
12 public ListNode deleteMiddle(ListNode head) {
13 // Edge case: If list has only 1 node, return null
14 if (head == null || head.next == null) {
15 return null;
16 }
17
18 ListNode slow = head;
19 // Start fast two steps ahead so slow lands on the node BEFORE middle
20 ListNode fast = head.next.next;
21
22 while (fast != null && fast.next != null) {
23 slow = slow.next;
24 fast = fast.next.next;
25 }
26
27 // Skip the middle node
28 slow.next = slow.next.next;
29
30 return head;
31 }
32}Python Solution for LeetCode 2095
1# Definition for singly-linked list.
2# class ListNode:
3# def __init__(self, val=0, next=None):
4# self.val = val
5# self.next = next
6class Solution:
7 def deleteMiddle(self, head: Optional[ListNode]) -> Optional[ListNode]:
8 # Edge case: If list has only 1 node, return None
9 if not head or not head.next:
10 return None
11
12 slow = head
13 # Start fast two steps ahead
14 fast = head.next.next
15
16 while fast and fast.next:
17 slow = slow.next
18 fast = fast.next.next
19
20 # slow is now at the predecessor of the middle node
21 slow.next = slow.next.next
22
23 return head