Delete Node at Specific Position in DSA Rust - Time & Space Complexity
We want to understand how long it takes to remove a node from a linked list at a certain position.
How does the time needed change when the list gets bigger?
Analyze the time complexity of the following code snippet.
fn delete_node_at_position(head: &mut Option>, pos: usize) {
if pos == 0 {
if let Some(node) = head.take() {
*head = node.next;
}
return;
}
let mut current = head.as_mut();
for _ in 0..pos - 1 {
if let Some(node) = current {
current = node.next.as_mut();
} else {
return;
}
}
if let Some(node) = current {
if let Some(next_node) = node.next.take() {
node.next = next_node.next;
}
}
}
This code removes a node at a given position from a singly linked list by moving through the list to find the node before the target.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Loop that moves through the list nodes to reach the position before the one to delete.
- How many times: Up to
pos - 1times, depending on the position.
As the position to delete moves further in the list, the code must check more nodes one by one.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | Up to 9 steps to reach position |
| 100 | Up to 99 steps to reach position |
| 1000 | Up to 999 steps to reach position |
Pattern observation: The number of steps grows roughly in direct proportion to the position number.
Time Complexity: O(n)
This means the time to delete a node grows linearly with the position in the list.
[X] Wrong: "Deleting a node at any position takes the same fixed time."
[OK] Correct: Because you must first move through the list to find the node before the one to delete, which takes longer for nodes farther down.
Understanding how linked list operations scale helps you explain your code clearly and shows you know how data structures work under the hood.
"What if the list was doubly linked? How would the time complexity of deleting a node at a specific position change?"
Practice
Solution
Step 1: Understand node deletion
Deleting a node means removing it from the list and connecting the previous node to the next node.Step 2: Apply to specific position
At a specific position, the node at that index is removed and neighbors are linked to maintain the list.Final Answer:
Removing the node located at that position and linking its neighbors -> Option AQuick Check:
Delete node = Remove and link neighbors [OK]
- Confusing deletion with insertion
- Thinking deletion swaps nodes
- Ignoring neighbor linking after deletion
Solution
Step 1: Check struct fields
Rust linked list nodes use Option for next to allow null and ownership.Step 2: Validate mutability
Mutability is controlled outside struct fields; 'mut' keyword inside struct is invalid.Final Answer:
struct Node { data: i32, next: Option } -> Option BQuick Check:
Option for next pointer [OK]
- Adding 'mut' inside struct fields
- Using Box<Node> without Option causing no null
- Using references (&Node) causing lifetime issues
fn main() {
let mut head = Some(Box::new(Node { data: 10, next: Some(Box::new(Node { data: 20, next: Some(Box::new(Node { data: 30, next: Some(Box::new(Node { data: 40, next: None })) })) })) }));
delete_at_position(&mut head, 2);
print_list(&head);
}
fn delete_at_position(head: &mut Option, pos: usize) {
if pos == 0 {
*head = head.as_mut().and_then(|node| node.next.take());
return;
}
let mut current = head.as_mut();
for _ in 0..pos-1 {
if let Some(node) = current {
current = node.next.as_mut();
}
}
if let Some(node) = current {
node.next = node.next.as_mut().and_then(|next_node| next_node.next.take());
}
}
fn print_list(head: &Option) {
let mut current = head;
while let Some(node) = current {
print!("{} -> ", node.data);
current = &node.next;
}
println!("null");
}
struct Node {
data: i32,
next: Option,
}Solution
Step 1: Identify node to delete at position 2
Position 2 node has data 30 in list 10 -> 20 -> 30 -> 40 -> null.Step 2: Remove node 30 and link 20 to 40
After deletion, list becomes 10 -> 20 -> 40 -> null.Final Answer:
10 -> 20 -> 40 -> null -> Option CQuick Check:
Deleted node 30 at pos 2 [OK]
- Deleting wrong node index
- Not linking neighbors correctly
- Confusing 0-based and 1-based positions
fn delete_at_position(head: &mut Option, pos: usize) {
let mut current = head.as_mut();
for _ in 0..pos {
if let Some(node) = current {
current = node.next.as_mut();
}
}
if let Some(node) = current {
node.next = node.next.as_mut().and_then(|next_node| next_node.next.take());
}
}Solution
Step 1: Analyze loop range for traversal
The loop runs from 0 to pos, moving current to node at pos, not previous node needed for deletion.Step 2: Check head deletion handling
Function does not handle pos 0 case, so head pointer is never updated if first node is deleted.Step 3: Summarize all issues
Loop skips previous node, no head update on pos 0, so all listed bugs exist.Final Answer:
All of the above -> Option AQuick Check:
Loop and head update bugs = All above [OK]
- Looping to node instead of previous node
- Ignoring deletion of head node
- Not updating head pointer on deletion
Solution
Step 1: Identify node at position 3
Position 3 node has value 35 in list 5 -> 15 -> 25 -> 35 -> 45 -> null.Step 2: Delete node 35 and link 25 to 45
After deletion, list becomes 5 -> 15 -> 25 -> 45 -> null.Final Answer:
5 -> 15 -> 25 -> 45 -> null -> Option DQuick Check:
Deleted node 35 at pos 3 [OK]
- Deleting wrong position node
- Not linking previous node to next
- Confusing 0-based indexing
Ready to prove it?
Pass the test and this pattern moves unknown
