Push Using Linked List Node in DSA Rust - Time & Space Complexity
We want to understand how long it takes to add a new item to the front of a linked list.
How does the time needed change as the list grows?
Analyze the time complexity of the following code snippet.
struct Node {
value: i32,
next: Option>,
}
fn push(head: &mut Option>, val: i32) {
let new_node = Box::new(Node { value: val, next: head.take() });
*head = Some(new_node);
}
This code adds a new node with a value to the front of a linked list.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Creating a new node and updating the head pointer.
- How many times: This happens once per push call, no loops or recursion involved.
Adding a node always takes the same steps, no matter how big the list is.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 3 (create node, update pointer) |
| 100 | 3 (same steps, no extra work) |
| 1000 | 3 (still the same fixed steps) |
Pattern observation: The time to push does not grow with the list size; it stays constant.
Time Complexity: O(1)
This means adding a new node to the front takes the same short time no matter how many nodes are already in the list.
[X] Wrong: "Adding a node takes longer as the list grows because we have to move through the list."
[OK] Correct: We only change the head pointer and the new node's next pointer; we never walk through the list when pushing.
Knowing that push on a linked list is quick and constant time shows you understand how pointers work and why linked lists are useful for fast insertions.
"What if we had to add a node at the end of the linked list instead? How would the time complexity change?"
Practice
push operation do in a linked list when using a node?Solution
Step 1: Understand push operation in linked list
The push operation adds a new node to the linked list.Step 2: Identify where the new node is added
In a singly linked list, push usually adds the new node at the start (head) of the list.Final Answer:
Adds a new node at the beginning of the list -> Option AQuick Check:
Push = Add at head [OK]
- Thinking push adds at the end
- Confusing push with pop
- Assuming push deletes nodes
Solution
Step 1: Check node creation with Box and linking
let new_node = Box::new(Node { data: 5, next: head }); head = Some(new_node); creates a boxed node with data 5 and next pointing to current head.Step 2: Assign new node as new head
Then head is updated to Some(new_node), correctly pushing at front.Final Answer:
let new_node = Box::new(Node { data: 5, next: head }); head = Some(new_node); -> Option CQuick Check:
Boxed node with next=head, then head=Some(new_node) [OK]
- Not boxing the node
- Not updating head correctly
- Setting next to None instead of head
struct Node {
data: i32,
next: Option,
}
fn push(head: &mut Option, data: i32) {
let new_node = Box::new(Node { data, next: head.take() });
*head = Some(new_node);
}
fn print_list(head: &Option) {
let mut current = head;
while let Some(node) = current {
print!("{} -> ", node.data);
current = &node.next;
}
println!("null");
}
fn main() {
let mut head = None;
push(&mut head, 10);
push(&mut head, 20);
push(&mut head, 30);
print_list(&head);
}Solution
Step 1: Trace push calls and list building
First push adds 10 as head. Second push adds 20 before 10. Third push adds 30 before 20.Step 2: Print list from head
Print starts at head (30), then 20, then 10, then null.Final Answer:
30 -> 20 -> 10 -> null -> Option BQuick Check:
Last pushed node is head, so list is 30->20->10->null [OK]
- Assuming push adds at end
- Confusing order of nodes
- Ignoring Option and Box usage
fn push(head: &mut Option, data: i32) {
let new_node = Box::new(Node { data, next: head });
*head = Some(new_node);
}Solution
Step 1: Analyze next field assignment
The next field expects Option, but head is &mut Option, a reference.Step 2: Correct usage with head.take()
Using head.take() moves the Option out, allowing ownership transfer to next.Final Answer:
Cannot assign &Option to next, must use head.take() -> Option AQuick Check:
Use head.take() to move ownership [OK]
- Assigning reference instead of owned Option
- Ignoring Rust ownership rules
- Thinking Box::new is invalid here
Solution
Step 1: Understand ownership in Rust linked list
Each node owns the next node via Box. To avoid leaks, ownership must be properly transferred.Step 2: Use head.take() to move ownership safely
head.take() replaces head with None and moves ownership to new node's next, preventing leaks.Final Answer:
Use head.take() to transfer ownership and avoid dangling references -> Option DQuick Check:
head.take() safely moves ownership, preventing leaks [OK]
- Using raw pointers causing unsafe code
- Calling drop manually causing double free
- Cloning nodes causing unnecessary copies
Ready to prove it?
Pass the test and this pattern moves unknown
