Traversal Forward and Backward in DSA Rust - Time & Space Complexity
We want to understand how long it takes to move through a list from start to end and then back again.
How does the time needed change as the list grows bigger?
Analyze the time complexity of the following code snippet.
fn traverse_forward_backward(list: &Vec<i32>) {
for i in 0..list.len() {
let _ = list[i]; // forward traversal
}
for i in (0..list.len()).rev() {
let _ = list[i]; // backward traversal
}
}
This code goes through the list from the first item to the last, then goes back from the last to the first.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Two separate loops each visiting every item once.
- How many times: Each loop runs exactly n times, where n is the list size.
As the list gets bigger, the total steps grow roughly twice as fast because we go forward and backward.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 20 (10 forward + 10 backward) |
| 100 | 200 (100 forward + 100 backward) |
| 1000 | 2000 (1000 forward + 1000 backward) |
Pattern observation: The total steps double as input size doubles, showing a linear growth.
Time Complexity: O(n)
This means the time to complete grows directly in proportion to the list size.
[X] Wrong: "Because there are two loops, the time complexity is O(n²)."
[OK] Correct: The loops run one after another, not nested, so their times add up, not multiply.
Understanding how simple forward and backward traversals scale helps you reason about more complex data operations confidently.
"What if we combined the forward and backward traversal into a single loop that visits two elements per step? How would the time complexity change?"
Practice
Solution
Step 1: Understand doubly linked list structure
A doubly linked list has nodes connected both forward and backward, allowing movement in both directions.Step 2: Define traversal forward and backward
Traversal forward means moving from the first node to the last node, and traversal backward means moving from the last node back to the first node.Final Answer:
Moving through the list from the first node to the last and then back from the last to the first -> Option BQuick Check:
Forward and backward traversal = Moving both ways [OK]
- Confusing traversal with skipping nodes
- Thinking traversal is only forward
- Assuming random movement is traversal
Solution
Step 1: Identify forward traversal in Rust
Forward traversal moves from current node to next node using the next pointer.Step 2: Check code correctness
while let Some(node) = current { println!("{}", node.value); current = node.next.as_deref_mut(); } uses current = node.next.as_deref_mut() which correctly moves forward. while let Some(node) = current { println!("{}", node.value); current = node.prev.as_deref_mut(); } moves backward, C is invalid syntax for linked list, D loops backward without condition.Final Answer:
while let Some(node) = current { println!("{}", node.value); current = node.next.as_deref_mut(); } -> Option CQuick Check:
Forward traversal uses next pointer [OK]
- Using prev pointer for forward traversal
- Incorrect loop syntax for linked list
- Ignoring option handling in Rust
struct Node { value: i32, prev: Option, next: Option }
fn traverse_backward(mut current: Option<&Node>) {
while let Some(node) = current {
print!("{} ", node.value);
current = node.prev.as_deref();
}
}
// Assume list nodes with values 1 -> 2 -> 3, current starts at node with value 3
Solution
Step 1: Understand backward traversal
Starting at node with value 3, moving backward means following prev pointers to 2, then 1.Step 2: Trace the print output
Prints 3 first, then 2, then 1, each followed by a space.Final Answer:
3 2 1 -> Option AQuick Check:
Backward traversal prints nodes in reverse order [OK]
- Confusing forward and backward order
- Assuming traversal starts at head
- Ignoring Option handling in Rust
fn traverse(mut current: Option<&Node>) {
while current.is_some() {
println!("{}", current.unwrap().value);
current = current.unwrap().next.as_deref();
}
}Solution
Step 1: Analyze unwrap() usage
Calling unwrap() twice without checking can panic if current becomes None between calls.Step 2: Suggest safer approach
Use while let Some(node) = current to safely unwrap once per iteration.Final Answer:
Using unwrap() multiple times causes panic if current is None -> Option DQuick Check:
Multiple unwrap() calls risk panic [OK]
- Confusing is_some() and is_none()
- Accessing wrong pointer for forward traversal
- Misusing println! macro
Solution
Step 1: Traverse forward collecting values
Starting at head (10), collect values in order: 10, 20, 30, 40.Step 2: Traverse backward from last node collecting values
Starting at tail (40), collect values backward: 40, 30, 20, 10.Final Answer:
Forward: [10, 20, 30, 40], Backward: [40, 30, 20, 10] -> Option AQuick Check:
Forward and backward vectors match traversal order [OK]
- Mixing order of forward and backward vectors
- Missing last node in traversal
- Confusing vector contents with node pointers
Ready to prove it?
Pass the test and this pattern moves unknown
