Delete a Node from Circular Linked List in DSA Rust - Time & Space Complexity
When deleting a node from a circular linked list, we want to know how the time needed changes as the list grows.
We ask: How many steps does it take to find and remove the node?
Analyze the time complexity of the following code snippet.
fn delete_node(head: &mut Option>, key: i32) {
if head.is_none() {
return;
}
let mut curr = head.as_mut().unwrap();
let mut prev = curr;
loop {
if curr.data == key {
prev.next = curr.next.take();
break;
}
prev = curr;
curr = curr.next.as_mut().unwrap();
if std::ptr::eq(curr.as_ref(), head.as_ref().unwrap().as_ref()) {
break;
}
}
}
This code searches the circular linked list for a node with the given key and removes it by adjusting links.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Looping through nodes one by one to find the node to delete.
- How many times: Up to n times, where n is the number of nodes in the list.
As the list grows, the number of steps to find the node grows roughly the same as the list size.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | Up to 10 steps |
| 100 | Up to 100 steps |
| 1000 | Up to 1000 steps |
Pattern observation: The steps grow linearly with the number of nodes.
Time Complexity: O(n)
This means the time to delete a node grows directly with the list size because we may need to check each node once.
[X] Wrong: "Deleting a node in a circular linked list always takes constant time because we just change links."
[OK] Correct: We must first find the node, which can take time proportional to the list size, so it is not always instant.
Understanding this helps you explain how linked lists work and how searching affects operation speed, a key skill in many coding challenges.
"What if the list was doubly linked? How would the time complexity of deleting a node change?"
Practice
Solution
Step 1: Understand the structure of a single-node circular linked list
In a circular linked list with one node, the node's next pointer points to itself.Step 2: Delete the only node
Removing this node means no nodes remain, so the list becomes empty (null).Final Answer:
The list becomes empty (null). -> Option CQuick Check:
Single node deleted = empty list [OK]
- Assuming the list still contains the deleted node
- Thinking the list points to itself after deletion
- Expecting an error instead of empty list
Solution
Step 1: Understand Rust ownership for circular references
Rust disallows direct cyclic ownership. Using Rc allows multiple owners and interior mutability.Step 2: Identify correct syntax for mutable circular linked list node
struct Node { data: i32, next: Option> } uses Option> which supports cycles and mutability safely.Final Answer:
struct Node { data: i32, next: Option> } -> Option DQuick Check:
Use Rc for circular mutable nodes [OK]
- Using plain Box<Node> causes ownership errors
- Using references (&Node) disallows ownership
- Using Node directly causes infinite size error
let mut head = create_circular_list(vec![1, 2, 3, 4]); delete_node(&mut head, 3); print_list(&head);What is the printed output?
Solution
Step 1: Understand the initial list
The list is circular with nodes 1, 2, 3, 4 linked in a loop.Step 2: Delete node with value 3
Node 3 is removed, so the list becomes 1 -> 2 -> 4, then back to 1.Final Answer:
1 -> 2 -> 4 -> 1 (circular) -> Option AQuick Check:
Deleted 3, list loops 1-2-4 [OK]
- Forgetting to link node 2 to node 4
- Printing null instead of circular loop
- Not deleting the correct node
fn delete_node(head: &mut Option>, key: i32) { let mut curr = head.clone().unwrap(); while curr.borrow().data != key { curr = curr.borrow().next.clone().unwrap(); } let next_node = curr.borrow().next.clone(); curr.borrow_mut().next = next_node.unwrap().borrow().next.clone(); }Solution
Step 1: Analyze the while loop condition
The loop continues until curr's data equals key, but no check if key exists, so it loops infinitely if key missing.Step 2: Check for missing exit condition
Without a break or stop when full circle is done, infinite loop occurs if key not found.Final Answer:
It causes infinite loop if key not found. -> Option AQuick Check:
No key check = infinite loop risk [OK]
- Assuming key always exists
- Not checking for full circle traversal
- Ignoring unwrap() panic risks
Solution
Step 1: Locate the last node in the circular list
The last node points back to head; find it by traversing until next points to head.Step 2: Update last node's next pointer and head
Set last node's next to head's next node, then update head to head's next to maintain circularity.Final Answer:
Find last node, link it to head's next, update head to head's next. -> Option BQuick Check:
Update last node and head to delete head safely [OK]
- Setting head to None breaks circularity
- Not updating last node's next pointer
- Deleting head without adjusting links
Ready to prove it?
Pass the test and this pattern moves unknown
