Left Side View of Binary Tree in DSA Rust - Time & Space Complexity
We want to understand how the time needed to find the left side view of a binary tree changes as the tree grows.
How does the number of nodes affect the work done to see the left side?
Analyze the time complexity of the following code snippet.
fn left_side_view(root: &Option>) -> Vec {
let mut result = Vec::new();
let mut queue = std::collections::VecDeque::new();
if let Some(node) = root {
queue.push_back(node.as_ref());
}
while !queue.is_empty() {
let level_size = queue.len();
for i in 0..level_size {
let node = queue.pop_front().unwrap();
if i == 0 {
result.push(node.val);
}
if let Some(left) = &node.left {
queue.push_back(left.as_ref());
}
if let Some(right) = &node.right {
queue.push_back(right.as_ref());
}
}
}
result
}
This code collects the leftmost node value at each level of the binary tree using a breadth-first search.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Visiting each node once in a loop.
- How many times: Exactly once per node, as each node is added and removed from the queue once.
As the number of nodes grows, the code visits each node once, so the work grows 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 linearly with the number of nodes.
Time Complexity: O(n)
This means the time to find the left side view grows directly with the number of nodes in the tree.
[X] Wrong: "The algorithm only looks at the left children, so it runs faster than visiting all nodes."
[OK] Correct: The code visits every node because it must check both left and right children to find the leftmost node at each level, so it still processes all nodes.
Understanding this linear time complexity helps you explain how breadth-first search explores trees level by level, a common pattern in many problems.
"What if we used depth-first search instead of breadth-first search? How would the time complexity change?"
Practice
Left Side View of a binary tree represent?Solution
Step 1: Understand the view perspective
The left side view shows nodes visible when looking at the tree from the left side.Step 2: Identify visible nodes
Only the first node at each level from the left is visible in this view.Final Answer:
Nodes visible when the tree is viewed from the left side -> Option CQuick Check:
Left side view = nodes seen from left [OK]
- Confusing left side view with right side view
- Including all leaf nodes instead of first nodes per level
- Thinking it shows deepest nodes only
Solution
Step 1: Check ownership and optional children
Rust binary trees use Option for nullable child nodes.Step 2: Validate correct syntax
Option allows for null or Some(child), which is correct for left and right.Final Answer:
struct TreeNode { val: i32, left: Option, right: Option } -> Option DQuick Check:
Use Option for nullable children [OK]
- Using direct TreeNode type for children (causes infinite size)
- Using references without lifetimes
- Omitting Option for nullable children
1
/ \
2 3
\ \
5 4
Assuming the function returns a vector of node values visible from the left side.Solution
Step 1: Identify nodes visible from left at each level
Level 0: 1, Level 1: 2 (left child), Level 2: 5 (right child of 2)Step 2: Collect visible nodes in order
Left side view nodes are [1, 2, 5]Final Answer:
[1, 2, 5] -> Option BQuick Check:
Left side nodes = [1, 2, 5] [OK]
- Choosing right child nodes instead of left
- Including nodes not visible from left
- Mixing order of nodes
fn left_side_view(root: Option) -> Vec<i32> {
let mut result = vec![];
let mut queue = vec![root.unwrap()];
while !queue.is_empty() {
let level_size = queue.len();
for i in 0..level_size {
let node = queue.remove(0);
if i == 0 {
result.push(node.val);
}
if let Some(left) = node.left {
queue.push(left);
}
if let Some(right) = node.right {
queue.push(right);
}
}
}
result
}
Solution
Step 1: Check root unwrap usage
Calling unwrap() on root without checking if it is null can cause panic if tree is empty.Step 2: Confirm other parts are correct
remove(0) works but is inefficient; order of pushing left then right is correct; result is returned.Final Answer:
Calling unwrap() on root without checking if it is null -> Option AQuick Check:
unwrap() on null causes panic [OK]
- Ignoring unwrap panic possibility
- Thinking remove(0) causes error (just slow)
- Confusing child push order
- Missing return statement
Solution
Step 1: Understand requirement for leftmost even nodes
We want only the first node at each level if its value is even.Step 2: Apply condition during traversal
Check if i == 0 (leftmost) and node.val % 2 == 0 before pushing to result.Final Answer:
Add a check inside the level loop: if i == 0 and node.val % 2 == 0, then push node.val to result -> Option AQuick Check:
Filter leftmost nodes by even value during traversal [OK]
- Filtering after traversal loses position info
- Ignoring leftmost position and filtering only by value
- Checking rightmost node instead of leftmost
Ready to prove it?
Pass the test and this pattern moves unknown
