You are given the head
of a linked list. Delete the middle node, and return the head
of the modified linked list.
The middle node of a linked list of size n
is the ⌊n / 2⌋th
node from the start using 0-based indexing, where ⌊x⌋
denotes the largest integer less than or equal to x
.
n
= 1
, 2
, 3
, 4
, and 5
, the middle nodes are 0
, 1
, 1
, 2
, and 2
, respectively.Example 1:
Input: head = [1,3,4,7,1,2,6] Output: [1,3,4,1,2,6] Explanation: The above figure represents the given linked list. The indices of the nodes are written below. Since n = 7, node 3 with value 7 is the middle node, which is marked in red. We return the new list after removing this node.
Example 2:
Input: head = [1,2,3,4] Output: [1,2,4] Explanation: The above figure represents the given linked list. For n = 4, node 2 with value 3 is the middle node, which is marked in red.
Example 3:
Input: head = [2,1] Output: [2] Explanation: The above figure represents the given linked list. For n = 2, node 1 with value 1 is the middle node, which is marked in red. Node 0 with value 2 is the only node remaining after removing node 1.
Constraints:
[1, 105]
.1 <= Node.val <= 105
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The goal is to remove the middle item from a linked list. The brute force method involves figuring out how many items are in the list and then walking to the middle to remove it.
Here's how the algorithm would work step-by-step:
def delete_middle_node(head):
if not head or not head.next:
return None
list_size = 0
current_node = head
while current_node:
list_size += 1
current_node = current_node.next
# Determine the middle node index
middle_node_index = list_size // 2
# Traverse to the node before the middle node
current_node = head
for _ in range(middle_node_index - 1):
current_node = current_node.next
# Bypass the middle node to delete it
current_node.next = current_node.next.next
return head
The goal is to remove the middle item from a connected chain of items. Since we don't know the exact length beforehand, we use a clever trick to find the middle quickly without counting everything first.
Here's how the algorithm would work step-by-step:
class Node:
def __init__(self, data):
self.data = data
self.next = None
def delete_middle_node(head_node):
if head_node is None or head_node.next is None:
return None
slow_pointer = head_node
fast_pointer = head_node
previous_to_slow = None
# Traverse list using two pointers to find middle node
while fast_pointer is not None and fast_pointer.next is not None:
fast_pointer = fast_pointer.next.next
previous_to_slow = slow_pointer
slow_pointer = slow_pointer.next
# At this point, slow_pointer points to the middle node.
# We need to update the previous node's next pointer.
if previous_to_slow is not None:
# This removes the middle node by skipping over it.
previous_to_slow.next = slow_pointer.next
return head_node
Case | How to Handle |
---|---|
Empty list (head is null) | Return null immediately as there's nothing to delete. |
List with one node | Delete the only node by setting the head to null and returning null. |
List with two nodes | Delete the second middle node, which is the second node in the list. |
List with an even number of nodes (e.g., 4 nodes) | Delete the second middle node (the node at position n/2 where n is number of nodes, considering 0-based indexing). |
List with an odd number of nodes (e.g., 5 nodes) | Delete the middle node (the node at position (n-1)/2 where n is number of nodes, considering 0-based indexing). |
Very long list (potential for slow pointer to catch up very late) | The fast and slow pointer approach remains efficient regardless of list length, as it only requires one traversal. |
List with duplicate values; middle node has same value as other nodes | The slow and fast pointer method finds the middle node's position independent of value, ensuring correct deletion. |
Memory constraints preventing list copying to find length | The slow and fast pointer approach operates in place without needing to copy the list, making it memory-efficient. |