Traversal and Printing a Linked List in DSA Rust - Time & Space Complexity
We want to understand how long it takes to go through all items in a linked list and print them.
How does the time needed change when the list gets bigger?
Analyze the time complexity of the following code snippet.
struct Node {
value: i32,
next: Option>,
}
fn print_list(head: &Option>) {
let mut current = head;
while let Some(node) = current {
println!("{}", node.value);
current = &node.next;
}
}
This code goes through each node in the linked list and prints its value one by one.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Loop that visits each node once.
- How many times: Exactly once per node, so as many times as the list length.
As the list grows, the number of print steps grows the same way.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 print steps |
| 100 | 100 print steps |
| 1000 | 1000 print steps |
Pattern observation: The work grows directly with the number of nodes, so doubling nodes doubles work.
Time Complexity: O(n)
This means the time to print grows in a straight line with the number of nodes in the list.
[X] Wrong: "Since we only print values, it must be faster than O(n)."
[OK] Correct: Even printing each value requires visiting every node once, so time still grows with list size.
Knowing how to analyze simple list traversal helps build confidence for more complex data structure questions.
"What if we changed the list to a doubly linked list? How would the time complexity of traversal and printing change?"
Practice
Solution
Step 1: Understand traversal meaning
Traversal means going through each element in order, like reading a list from start to finish.Step 2: Match with linked list action
Visiting each node one by one from start to end matches the idea of traversal.Final Answer:
Visiting each node one by one from start to end -> Option CQuick Check:
Traversal = Visit nodes in order [OK]
- Confusing traversal with adding or deleting nodes
- Thinking traversal means changing node order
list?Solution
Step 1: Check traversal logic
let mut current = &list.head; while let Some(node) = current { println!("{}", node.value); current = &node.next; } uses a mutable reference to current node and loops while current is Some(node), printing value and moving to next node.Step 2: Verify other options
for node in list { println!("{}", node.value); } tries for loop on list directly (not valid without iterator). while list.head.is_some() { println!("{}", list.head.value); list.head = list.head.next; } mutates list head which is unsafe. let mut current = list.head; loop { println!("{}", current.value); } loops infinitely without checking for None.Final Answer:
Option A code snippet -> Option AQuick Check:
Correct traversal uses while let Some(node) = current [OK]
- Trying to loop directly over list without iterator
- Not checking for None to stop loop
- Mutating list head during traversal
struct Node {
value: i32,
next: Option,
}
fn print_list(head: &Option) {
let mut current = head;
while let Some(node) = current {
print!("{} -> ", node.value);
current = &node.next;
}
println!("null");
}
fn main() {
let list = Some(Box::new(Node { value: 1, next: Some(Box::new(Node { value: 2, next: Some(Box::new(Node { value: 3, next: None })) })) }));
print_list(&list);
}Solution
Step 1: Understand list structure
The list nodes are 1 pointing to 2, which points to 3, which points to None.Step 2: Trace print_list function
It prints each node's value followed by ' -> ', then prints 'null' at the end.Final Answer:
1 -> 2 -> 3 -> null -> Option BQuick Check:
Print nodes in order with arrows [OK]
- Printing nodes in reverse order
- Missing arrows or null at end
- Printing values without separators
fn print_list(mut head: Option) {
while let Some(node) = head {
println!("{}", node.value);
head = node.next;
}
}Solution
Step 1: Analyze ownership in loop
The code takes ownership of head and nodes inside the loop, consuming the list and preventing reuse.Step 2: Suggest fix using references
Use references (&Option) and iterate without consuming ownership to allow reuse.Final Answer:
Code moves ownership of nodes, so it cannot be reused after printing -> Option DQuick Check:
Ownership moved inside loop causes consumption [OK]
- Ignoring ownership rules causing compile errors
- Not updating head causing infinite loops
- Confusing print! and println! macros
fn print_even(head: &Option) {
let mut current = head;
while let Some(node) = current {
// Your code here
current = &node.next;
}
}Solution
Step 1: Add condition inside traversal
Check if node.value is even using modulo operator and print only if true.Step 2: Keep traversal unchanged
Continue moving current to next node regardless of value to visit all nodes.Final Answer:
Add an if check: if node.value % 2 == 0 { println!("{}", node.value); } -> Option AQuick Check:
Filter values inside traversal with if condition [OK]
- Trying to modify next pointer during traversal
- Filtering after traversal instead of during
- Printing odd values instead of even
Ready to prove it?
Pass the test and this pattern moves unknown
