Tree Traversal Inorder Left Root Right in DSA Rust - Time & Space Complexity
We want to understand how the time needed to visit all nodes in a tree grows as the tree gets bigger.
How does the number of steps change when the tree has more nodes?
Analyze the time complexity of the following code snippet.
struct Node {
val: i32,
left: Option>,
right: Option>,
}
fn inorder_traversal(node: &Option>) {
if let Some(n) = node {
inorder_traversal(&n.left);
println!("{}", n.val);
inorder_traversal(&n.right);
}
}
This code visits each node in a tree in the order: left child, then root, then right child.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive calls visiting each node once.
- How many times: Once per node in the tree.
Each node is visited exactly once, so the total steps grow directly with the number of nodes.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 visits |
| 100 | About 100 visits |
| 1000 | About 1000 visits |
Pattern observation: The work grows in a straight line with the number of nodes.
Time Complexity: O(n)
This means the time to complete the traversal grows directly with the number of nodes in the tree.
[X] Wrong: "Because recursion is involved, the time must be exponential or very large."
[OK] Correct: Each node is visited only once, so the total steps grow linearly, not exponentially.
Understanding this traversal and its time cost helps you explain how tree operations work efficiently in many real problems.
"What if the tree is very unbalanced, like a linked list? How would the time complexity change?"
Practice
Solution
Step 1: Understand inorder traversal definition
Inorder traversal visits nodes in the order: left subtree first, then the root node, and finally the right subtree.Step 2: Match the order with options
Left subtree, Root node, Right subtree matches the left-root-right order exactly.Final Answer:
Left subtree, Root node, Right subtree -> Option AQuick Check:
Inorder = Left, Root, Right [OK]
- Confusing inorder with preorder or postorder
- Mixing up the order of root and subtrees
- Thinking inorder visits root first
Solution
Step 1: Understand Rust ownership and references for trees
Binary trees in Rust often use Option to allow null and heap allocation. Passing by reference (&Option) avoids ownership transfer during traversal.Step 2: Check each option's signature
fn inorder(node: &Option) { /* traversal code */ } uses a reference to Option, which is correct for traversal without ownership moves. Others either take ownership or incorrect types.Final Answer:
fn inorder(node: &Option) { /* traversal code */ } -> Option BQuick Check:
Use &Option for safe traversal [OK]
- Taking ownership of nodes causing move errors
- Using plain TreeNode instead of Box or Option
- Returning traversal result without proper ownership
struct TreeNode {
val: i32,
left: Option,
right: Option,
}
fn inorder(node: &Option) {
if let Some(n) = node {
inorder(&n.left);
print!("{} ", n.val);
inorder(&n.right);
}
}
fn main() {
let tree = Some(Box::new(TreeNode {
val: 2,
left: Some(Box::new(TreeNode {
val: 1,
left: None,
right: None,
})),
right: Some(Box::new(TreeNode {
val: 3,
left: None,
right: None,
})),
}));
inorder(&tree);
}Solution
Step 1: Understand the tree structure
The root node has value 2, left child 1, right child 3.Step 2: Trace inorder traversal
Inorder visits left subtree (1), then root (2), then right subtree (3). So output is "1 2 3 "Final Answer:
1 2 3 -> Option CQuick Check:
Inorder prints left-root-right: 1 2 3 [OK]
- Printing root before left subtree
- Confusing preorder or postorder output
- Ignoring spaces in output
fn inorder(node: Option) {
if let Some(n) = node {
inorder(n.left);
print!("{} ", n.val);
inorder(n.right);
}
}Solution
Step 1: Identify ownership problem in parameter
The function takes ownership of node, so recursive calls move ownership of n.left and n.right, which is invalid after first call.Step 2: Fix by using references
Changing parameter to &Option and calling inorder(&n.left) and inorder(&n.right) avoids ownership moves and allows safe recursion.Final Answer:
Change parameter to &Option and call inorder(&n.left) and inorder(&n.right) -> Option DQuick Check:
Use references to avoid ownership moves in recursion [OK]
- Passing ownership causing move errors
- Trying to use Option<&Box<TreeNode>> incorrectly
- Ignoring Rust's ownership rules in recursion
Solution
Step 1: Understand inorder traversal collection
Inorder means collect left subtree values first, then root value, then right subtree values.Step 2: Check each code snippet's order and ownership
fn inorder_collect(node: &Option) -> Vec<i32> { let mut vals = Vec::new(); if let Some(n) = node { vals.extend(inorder_collect(&n.left)); vals.push(n.val); vals.extend(inorder_collect(&n.right)); } vals } correctly uses references, collects left subtree, then root, then right subtree, returning combined vector.Final Answer:
fn inorder_collect(node: &Option) -> Vec<i32> { let mut vals = Vec::new(); if let Some(n) = node { vals.extend(inorder_collect(&n.left)); vals.push(n.val); vals.extend(inorder_collect(&n.right)); } vals } -> Option AQuick Check:
Collect left, root, right in vector [OK]
- Wrong order of pushing values
- Taking ownership instead of references
- Appending right subtree before left
Ready to prove it?
Pass the test and this pattern moves unknown
