Top View of Binary Tree in DSA Rust - Time & Space Complexity
We want to understand how the time needed to find the top view of a binary tree changes as the tree grows.
How does the number of nodes affect the work done to get the top view?
Analyze the time complexity of the following code snippet.
use std::collections::{HashMap, VecDeque};
fn top_view(root: &Option>) -> Vec {
let mut queue = VecDeque::new();
let mut map = HashMap::new();
if let Some(node) = root {
queue.push_back((node.as_ref(), 0));
}
while let Some((node, hd)) = queue.pop_front() {
map.entry(hd).or_insert(node.val);
if let Some(left) = &node.left {
queue.push_back((left.as_ref(), hd - 1));
}
if let Some(right) = &node.right {
queue.push_back((right.as_ref(), hd + 1));
}
}
let mut keys: Vec<_> = map.keys().cloned().collect();
keys.sort();
keys.iter().map(|k| *map[k]).collect()
}
struct TreeNode {
val: i32,
left: Option>,
right: Option>,
}
This code finds the top view of a binary tree by visiting each node once and tracking horizontal distances.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that visits each node once.
- How many times: Once for every node in the tree (n times).
As the number of nodes grows, the work grows roughly the same amount.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 visits and map insertions |
| 100 | About 100 visits and map insertions |
| 1000 | About 1000 visits and map insertions |
Pattern observation: The operations increase linearly as the tree size increases.
Time Complexity: O(n)
This means the time to find the top view grows directly with the number of nodes in the tree.
[X] Wrong: "The top view requires checking all paths, so it must be more than linear time."
[OK] Correct: Each node is visited only once in a simple breadth-first manner, so the work grows linearly, not more.
Understanding this linear time approach shows you can handle tree traversals efficiently, a key skill in many coding challenges.
"What if we used a depth-first search instead of breadth-first search? How would the time complexity change?"
Practice
top view of a binary tree represent?Solution
Step 1: Understand the top view concept
The top view of a binary tree shows all nodes that are visible when looking down vertically from above the tree.Step 2: Compare with other views
Left, right, and bottom views show nodes visible from those sides, not from the top.Final Answer:
Nodes visible when the tree is viewed from the top -> Option AQuick Check:
Top view = nodes seen from above [OK]
- Confusing top view with left or right view
- Thinking bottom view is the same as top view
Solution
Step 1: Identify the need for horizontal distance mapping
Top view requires tracking nodes by their horizontal distance from the root, which can be negative or positive integers.Step 2: Choose a data structure for key-value mapping
A HashMap with key as horizontal distance (i32) and value as Node is ideal for quick lookups and updates.Final Answer:
HashMap -> Option AQuick Check:
Use HashMap for horizontal distance mapping [OK]
- Using Vec which doesn't map keys to values
- Using LinkedList which is inefficient for lookups
- Using BinaryHeap which is for priority queues
struct Node {
val: i32,
left: Option,
right: Option,
}
// Tree:
// 1
// / \
// 2 3
// \ \
// 4 5
fn main() {
let root = Node {
val: 1,
left: Some(Box::new(Node {
val: 2,
left: None,
right: Some(Box::new(Node { val: 4, left: None, right: None })),
})),
right: Some(Box::new(Node {
val: 3,
left: None,
right: Some(Box::new(Node { val: 5, left: None, right: None })),
})),
};
// Assume top_view function prints top view nodes in order from left to right
top_view(&root);
}Solution
Step 1: Assign horizontal distances to nodes
Root (1) is at 0, left child (2) at -1, right child (3) at +1, node 4 at 0 (right child of 2), node 5 at +2 (right child of 3).Step 2: Determine top view nodes by horizontal distance
For each horizontal distance, the first node encountered from top is chosen: -1: 2, 0: 1, +1: 3, +2: 5. Node 4 at 0 is below 1, so ignored.Final Answer:
[2, 1, 3, 5] -> Option BQuick Check:
Top view nodes by horizontal distance = [2, 1, 3, 5] [OK]
- Including nodes below first at same horizontal distance
- Ignoring horizontal distances for nodes
- Confusing order of output
fn top_view(root: &Node) {
let mut map = std::collections::HashMap::new();
let mut queue = std::collections::VecDeque::new();
queue.push_back((root, 0));
while let Some((node, hd)) = queue.pop_front() {
// Insert node if horizontal distance not present
map.entry(hd).or_insert(node.val);
if let Some(left) = &node.left {
queue.push_back((left, hd - 1));
}
if let Some(right) = &node.right {
queue.push_back((right, hd + 1));
}
}
for key in map.keys() {
println!("{}", map[key]);
}
}Solution
Step 1: Analyze map insertion and printing
The code inserts nodes correctly using or_insert to keep first node per horizontal distance.Step 2: Check output order
HashMap keys are unordered, so iterating with map.keys() prints nodes in random order, not left to right.Final Answer:
The map keys are not sorted before printing, so output order is random -> Option CQuick Check:
Sort keys before printing top view [OK]
- Assuming HashMap keys are ordered
- Ignoring empty tree case (not asked here)
- Thinking queue initialization is wrong
Solution
Step 1: Understand top view requires horizontal distance and level
Top view needs to know horizontal distance and the vertical level to pick the topmost node at each horizontal distance.Step 2: Choose approach that tracks horizontal distance and level
Recursive traversal passing horizontal distance and level, storing first node per horizontal distance with smallest level, correctly computes top view.Final Answer:
Use recursion with horizontal distance and level to track top nodes -> Option DQuick Check:
Track horizontal distance and level recursively [OK]
- Ignoring horizontal distance in traversal
- Using stack without tracking levels
- Printing nodes in preorder without filtering
Ready to prove it?
Pass the test and this pattern moves unknown
