Height of Binary Tree in DSA Rust - Time & Space Complexity
We want to understand how long it takes to find the height of a binary tree as the tree grows.
How does the time needed change when the tree has more nodes?
Analyze the time complexity of the following code snippet.
fn height(node: &Option>) -> i32 {
match node {
None => 0,
Some(n) => {
let left_height = height(&n.left);
let right_height = height(&n.right);
1 + left_height.max(right_height)
}
}
}
This code finds the height of a binary tree by checking the height of left and right subtrees recursively.
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.
As the number of nodes grows, the function visits each node once to calculate height.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 calls |
| 100 | About 100 calls |
| 1000 | About 1000 calls |
Pattern observation: The number of operations grows directly with the number of nodes.
Time Complexity: O(n)
This means the time to find the height grows linearly with the number of nodes in the tree.
[X] Wrong: "The height function only checks one path, so it runs in O(log n)."
[OK] Correct: The function visits every node to find the max height, so it must check all paths, not just one.
Understanding this helps you explain how recursive tree algorithms work and why visiting all nodes matters.
"What if the tree was a linked list (all nodes have only one child)? How would the time complexity change?"
Practice
Solution
Step 1: Understand height definition
The height of a binary tree is the number of edges on the longest path from the root to a leaf.Step 2: Apply to single node tree
With only one node (root), the longest path has length 0 edges.Final Answer:
0 -> Option DQuick Check:
Single node tree height = 0 [OK]
- Confusing height with number of nodes
- Thinking empty tree has height 1
- Assuming height starts at 1
struct Node { left: Option, right: Option }?Solution
Step 1: Analyze parameter types
The tree nodes are wrapped in Option to allow nullability and heap allocation.Step 2: Choose correct reference type
Passing a reference to Option (&Option) avoids moving ownership and allows checking for None.Final Answer:
fn height(node: &Option) -> usize -> Option AQuick Check:
Use &Option to handle nullable nodes safely [OK]
- Passing Node by value moves ownership
- Using Option<Node> instead of Option
- Using &Node misses None case
struct Node {
left: Option<Box<Node>>,
right: Option<Box<Node>>,
}
fn height(node: &Option<Box<Node>>) -> usize {
match node {
None => 0,
Some(n) => 1 + height(n.left).max(height(n.right)),
}
}
fn main() {
let leaf = Node { left: None, right: None };
let left_child = Node { left: Some(Box::new(leaf)), right: None };
let root = Some(Box::new(Node { left: Some(Box::new(left_child)), right: None }));
println!("{}", height(&root));
}Solution
Step 1: Trace leaf node height
The leaf node has no children, so height = 1 (0 + 1).Step 2: Trace left_child height
Left_child has left = leaf (height 1), right = None (height 0), so height = 1 + max(1,0) = 2.Step 3: Trace root height
Root has left = left_child (height 2), right = None (height 0), so height = 1 + max(2,0) = 3.Final Answer:
3 -> Option CQuick Check:
Height counts nodes on longest path = 3 [OK]
- Counting edges instead of nodes
- Ignoring None children
- Misreading recursive calls
fn height(node: Option<Box<Node>>) -> usize {
if node.is_none() {
return 0;
}
let n = node.unwrap();
1 + height(n.left).max(height(n.right))
}Solution
Step 1: Identify ownership issue
Calling unwrap() moves ownership of node, making recursive calls invalid as ownership is lost.Step 2: Fix by using references
Changing parameter to &Option<Box<Node>> allows borrowing without moving ownership, enabling safe recursion.Final Answer:
Change parameter to &Option<Box<Node>> and use references to avoid moving ownership -> Option BQuick Check:
Use references to prevent ownership errors in recursion [OK]
- Using unwrap() moves ownership
- Ignoring ownership rules
- Changing return values incorrectly
(parent, child). Which approach correctly computes the height of the tree in Rust?Solution
Step 1: Understand input format
The vector of edges gives parent-child pairs but no direct tree structure.Step 2: Build tree structure
Construct nodes and link children to parents to form the tree, identifying the root (node with no parent).Step 3: Compute height recursively
Starting from root node, recursively calculate height by finding max height of left and right subtrees.Final Answer:
Build the tree nodes from edges, then recursively compute height from root node -> Option AQuick Check:
Build tree first, then compute height recursively [OK]
- Using edge count as height
- Ignoring tree structure
- Assuming max child value equals height
Ready to prove it?
Pass the test and this pattern moves unknown
