Delete Node at Beginning in DSA Rust - Time & Space Complexity
We want to know how long it takes to remove the first node from a linked list.
How does the time needed change when the list grows bigger?
Analyze the time complexity of the following code snippet.
struct Node {
data: i32,
next: Option>,
}
fn delete_at_beginning(head: &mut Option>) {
if head.is_some() {
let next_node = head.as_mut().unwrap().next.take();
*head = next_node;
}
}
This code removes the first node from a linked list by changing the head pointer to the next node.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Accessing and updating the head pointer once.
- How many times: Exactly one time per call, no loops or recursion.
Removing the first node takes the same steps no matter how big the list is.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 1 |
| 100 | 1 |
| 1000 | 1 |
Pattern observation: The work stays the same even if the list grows larger.
Time Complexity: O(1)
This means deleting the first node takes a constant amount of time no matter the list size.
[X] Wrong: "Deleting the first node takes longer if the list is bigger because we have to check all nodes."
[OK] Correct: We only change the head pointer once; we do not look at other nodes.
Knowing this helps you explain why some linked list operations are very fast, building confidence in your understanding.
"What if we had to delete the last node instead? How would the time complexity change?"
Practice
Solution
Step 1: Understand the head pointer role
The head points to the first node in the list, so deleting the first node means changing the head.Step 2: Update the head to the next node
After removing the first node, the head should point to the second node, effectively removing the first node from the list.Final Answer:
Removes the first node and updates the head to the next node -> Option CQuick Check:
Delete at beginning = remove first node [OK]
- Trying to remove the last node instead of the first
- Not updating the head pointer after deletion
- Deleting all nodes instead of just one
head?Solution
Step 1: Understand Rust Option handling for linked lists
In Rust, linked lists often use Option. To delete the first node, we take the head and replace it with its next node safely.Step 2: Use
take()andand_then()to update headhead.take()removes the current head, andand_then(|node| node.next)sets head to the next node, deleting the first.Final Answer:
head = head.take().and_then(|node| node.next); -> Option AQuick Check:
Use take() and and_then() to delete first node [OK]
- Trying to assign head.next directly without handling Option
- Using unwrap() which can panic if head is None
- Assigning head.next to head causing infinite loop
let mut head = Some(Box::new(Node { value: 10, next: Some(Box::new(Node { value: 20, next: Some(Box::new(Node { value: 30, next: None })) })) }));
head = head.take().and_then(|node| node.next);
Print the list values in order.Solution
Step 1: Initial list values
The list starts as 10 -> 20 -> 30 -> None.Step 2: Delete the first node
Usinghead.take().and_then(|node| node.next)removes the node with value 10 and sets head to node with value 20.Final Answer:
[20, 30] -> Option DQuick Check:
After deletion, list starts at 20 [OK]
- Forgetting to update head, so list stays same
- Assuming deletion removes last node
- Confusing node values order after deletion
fn delete_first(mut head: Option) -> Option {
head = head.unwrap().next;
head
}Solution
Step 1: Check unwrap() usage
Calling unwrap() on an Option that might be None will cause the program to panic at runtime.Step 2: Safe deletion requires handling None
Before unwrap(), code should check if head is Some or use methods like take() and and_then() to avoid panic.Final Answer:
Using unwrap() without checking if head is None causes panic -> Option AQuick Check:
unwrap() on None causes panic [OK]
- Ignoring possibility of empty list (None)
- Not returning updated head properly
- Confusing ownership and borrowing in function
Solution
Step 1: Handle Option safely with take() and and_then()
Usinghead.take().and_then(|node| node.next)safely removes the first node and returns the next node or None if empty.Step 2: Return updated head
Assign the result back to head and return it, ensuring the function works for empty and non-empty lists.Final Answer:
fn delete_first(mut head: Option) -> Option { head = head.take().and_then(|node| node.next); head } -> Option BQuick Check:
Use take() and and_then() for safe deletion [OK]
- Using unwrap() without checking for None
- Accessing head.next directly on Option type
- Not returning the updated head after deletion
Ready to prove it?
Pass the test and this pattern moves unknown
