Top View of Binary Tree in DSA C++ - 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.
// Function to print top view of binary tree
void topView(Node* root) {
if (!root) return;
map topNode;
queue> q;
q.push({root, 0});
while (!q.empty()) {
auto p = q.front(); q.pop();
Node* node = p.first;
int hd = p.second;
if (topNode.find(hd) == topNode.end())
topNode[hd] = node->data;
if (node->left) q.push({node->left, hd - 1});
if (node->right) q.push({node->right, hd + 1});
}
for (auto it : topNode)
cout << it.second << " ";
}
This code uses a breadth-first search (BFS) to visit nodes level by level and records the first node encountered at each horizontal distance (hd) using a map.
- Primary loop: BFS while loop visits each of the n nodes exactly once.
- Per-node operations: Queue pop (O(1)), map find (O(log w), where w is current map size ≤ n), conditional insert (O(log n) at most once per unique hd).
- Key insight: Map operations (find/insert) occur for every node, not just unique hd.
The BFS visits n nodes, but each visit includes O(log n) map work. Total work: O(n log n). Printing traverses the map once: O(w) where w ≤ n (negligible).
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 * log(10) ≈ 30 map ops + queue work |
| 100 | About 100 * log(100) ≈ 700 map ops |
| 1000 | About 1000 * log(1000) ≈ 10,000 map ops |
Pattern observation: Grows as n log n, faster than linear due to map lookups per node.
Time Complexity: O(n log n)
Dominated by n map operations, each O(log n). Space: O(w) for map + O(w) queue, worst O(n).
[X] Wrong: "Visits each node once, map only inserts unique hd (≤ n), so O(n)."
[OK] Correct: Map find runs for every node (n times), each O(log n), even if insert skipped. Total: O(n log n).
Spotting the hidden log n from map usage per node distinguishes solid analysis. Optimize with unordered_map (avg O(n)) or vertical order traversal tweaks.
"What if we used unordered_map instead of map? How would the time complexity change in average/worst case?"
Practice
top view of a binary tree represent?Solution
Step 1: Understand the meaning of top view
The top view of a binary tree shows nodes that are visible when looking down vertically from above the tree.Step 2: Compare with other views
Left or right views show nodes visible from sides, and leaf nodes are only the bottom nodes, so they are different.Final Answer:
Nodes visible when the tree is viewed from above -> Option DQuick Check:
Top view = nodes seen from above [OK]
- Confusing top view with left or right view
- Thinking top view shows all leaf nodes
- Assuming top view includes hidden nodes
Solution
Step 1: Identify the need for horizontal distance mapping
Top view requires storing nodes by their horizontal distance from root, which can be negative or positive keys.Step 2: Choose container supporting key-value pairs with sorted keys
std::map stores keys in sorted order and allows negative keys, unlike vector which uses indices starting at 0.Final Answer:
std::map -> Option AQuick Check:
Use map for horizontal distance keys [OK]
- Using vector which can't handle negative keys
- Using stack or queue which don't map keys
- Not sorting nodes by horizontal distance
1
/ \
2 3
\ \
4 5
\ \
6 7
Solution
Step 1: Assign horizontal distances (HD) to nodes
Root 1 has HD=0; left child 2 is HD=-1; right child 3 is HD=1; 4 is right of 2 so HD=0; 5 is right of 3 so HD=2; 6 is right of 4 so HD=1; 7 is right of 5 so HD=3.Step 2: Select first node at each HD from top to bottom
HD=-1: 2; HD=0: 1; HD=1: 3; HD=2: 5; HD=3: 7. Nodes 4 and 6 are hidden behind 1 and 3 respectively.Final Answer:
[2, 1, 3, 5, 7] -> Option AQuick Check:
Top view nodes by HD = [2,1,3,5,7] [OK]
- Including nodes hidden behind others at same HD
- Mixing order of nodes in output
- Ignoring horizontal distance calculation
std::map topViewMap;
std::queue> q;
q.push({root, 0});
while(!q.empty()) {
auto p = q.front(); q.pop();
Node* node = p.first;
int hd = p.second;
if(topViewMap.find(hd) == topViewMap.end())
topViewMap[hd] = node->data;
if(node->left) q.push({node->left, hd - 1});
if(node->right) q.push({node->right, hd + 1});
}
Solution
Step 1: Check node pointer usage inside loop
The code accesses node->left and node->right without verifying if node is nullptr, which can cause runtime errors if node is null.Step 2: Verify other parts of code
Horizontal distances are updated correctly; queue is initialized properly; map choice is valid though unordered_map could be faster but not an error.Final Answer:
Not checking if node is nullptr before accessing node->left and node->right -> Option CQuick Check:
Always check node != nullptr before child access [OK]
- Ignoring nullptr checks causing crashes
- Confusing horizontal distance updates
- Assuming map choice causes errors
Solution
Step 1: Understand top view node selection criteria
Top view shows the first node encountered at each horizontal distance when traversing level by level (top to bottom, left to right).Step 2: Clarify why first node in level order is chosen
Because level order visits nodes by increasing depth, the first node at a horizontal distance is the topmost visible node.Final Answer:
The node that appears first in level order traversal at that horizontal distance -> Option BQuick Check:
Top view = first node per horizontal distance in level order [OK]
- Choosing node by max value instead of position
- Picking last node instead of first in level order
- Ignoring level order traversal importance
Ready to prove it?
Pass the test and this pattern moves unknown
