Top View of Binary Tree in DSA Go - 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.
func topView(root *Node) []int {
if root == nil {
return []int{}
}
type pair struct {
node *Node
hd int
}
queue := []pair{{root, 0}}
hdMap := map[int]int{}
minHd, maxHd := 0, 0
for len(queue) > 0 {
p := queue[0]
queue = queue[1:]
if _, ok := hdMap[p.hd]; !ok {
hdMap[p.hd] = p.node.data
}
if p.node.left != nil {
queue = append(queue, pair{p.node.left, p.hd - 1})
if p.hd-1 < minHd {
minHd = p.hd - 1
}
}
if p.node.right != nil {
queue = append(queue, pair{p.node.right, p.hd + 1})
if p.hd+1 > maxHd {
maxHd = p.hd + 1
}
}
}
result := []int{}
for i := minHd; i <= maxHd; i++ {
result = append(result, hdMap[i])
}
return result
}
This code finds the top view of a binary tree by doing a level order traversal and tracking horizontal distances.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that processes each node once in a queue.
- How many times: Exactly once per node in the tree (n times).
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 and checks |
| 100 | About 100 visits and checks |
| 1000 | About 1000 visits and checks |
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 in direct proportion to the number of nodes in the tree.
[X] Wrong: "The code visits nodes multiple times, so the time is more than linear."
[OK] Correct: Each node is added to the queue once and processed once, so the total work is proportional to the number of nodes.
Understanding this linear time complexity helps you explain how tree traversals work efficiently and shows you can analyze common tree problems clearly.
"What if we used a depth-first traversal instead of breadth-first? 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 includes all nodes visible when looking down vertically from above the tree.Step 2: Differentiate from other views
Left or right views show nodes from side angles, while top view shows nodes from above.Final Answer:
Nodes visible when the tree is viewed from above -> Option CQuick Check:
Top view = nodes seen from above [OK]
- Confusing top view with left or right view
- Including all leaf nodes as top view
- Thinking top view shows all nodes
Solution
Step 1: Identify the need for horizontal distance mapping
Top view requires tracking nodes by their horizontal distance from root to avoid duplicates.Step 2: Choose data structure supporting key-value pairs
A map with horizontal distance as key stores the first node at each horizontal distance efficiently.Final Answer:
Map with horizontal distance as key -> Option AQuick Check:
Use map for horizontal distance keys [OK]
- Using slice or array without horizontal distance keys
- Using linked list which lacks key access
- Ignoring horizontal distance concept
type Node struct {
Val int
Left, Right *Node
}
func topView(root *Node) []int {
if root == nil {
return []int{}
}
type pair struct { node *Node; hd int }
queue := []pair{{root, 0}}
m := map[int]int{}
res := []int{}
for len(queue) > 0 {
p := queue[0]
queue = queue[1:]
if _, ok := m[p.hd]; !ok {
m[p.hd] = p.node.Val
}
if p.node.Left != nil {
queue = append(queue, pair{p.node.Left, p.hd - 1})
}
if p.node.Right != nil {
queue = append(queue, pair{p.node.Right, p.hd + 1})
}
}
keys := []int{}
for k := range m {
keys = append(keys, k)
}
sort.Ints(keys)
for _, k := range keys {
res = append(res, m[k])
}
return res
}
root := &Node{Val: 1}
root.Left = &Node{Val: 2}
root.Right = &Node{Val: 3}
root.Left.Right = &Node{Val: 4}
root.Left.Right.Right = &Node{Val: 5}
root.Left.Right.Right.Right = &Node{Val: 6}
fmt.Println(topView(root))Solution
Step 1: Traverse nodes with horizontal distances
Root(1) at hd=0, Left(2) at hd=-1, Right(3) at hd=1, Left.Right(4) at hd=0 (ignored), Left.Right.Right(5) at hd=1 (ignored), Left.Right.Right.Right(6) at hd=2.Step 2: Collect first nodes at each horizontal distance
hd=-1:2, hd=0:1, hd=1:3, hd=2:6Final Answer:
[2 1 3 6] -> Option BQuick Check:
Top view nodes by hd sorted: 2,1,3,6 [OK]
- Including nodes overwritten at same horizontal distance
- Ignoring horizontal distance ordering
- Confusing top view with level order
func topView(root *Node) []int {
if root == nil {
return []int{}
}
type pair struct { node *Node; hd int }
queue := []pair{{root, 0}}
m := map[int]int{}
res := []int{}
for len(queue) > 0 {
p := queue[0]
queue = queue[1:]
m[p.hd] = p.node.Val
if p.node.Left != nil {
queue = append(queue, pair{p.node.Left, p.hd - 1})
}
if p.node.Right != nil {
queue = append(queue, pair{p.node.Right, p.hd + 1})
}
}
keys := []int{}
for k := range m {
keys = append(keys, k)
}
sort.Ints(keys)
for _, k := range keys {
res = append(res, m[k])
}
return res
}Solution
Step 1: Analyze map assignment inside loop
The code assigns m[p.hd] = p.node.Val every time, overwriting previous values at same horizontal distance.Step 2: Understand top view requirement
Top view requires storing only the first node encountered at each horizontal distance, so overwriting causes incorrect output.Final Answer:
It overwrites nodes at the same horizontal distance, losing top view nodes -> Option AQuick Check:
Overwrite causes wrong top view [OK]
- Overwriting map entries instead of checking existence
- Ignoring horizontal distance uniqueness
- Not sorting keys before output
Solution
Step 1: Understand the problem with duplicates
When nodes share horizontal distance and level, top view must pick one node per horizontal distance.Step 2: Modify map to track smallest value
Instead of storing first node only, update stored node if a smaller value is found at the same horizontal distance.Step 3: Implement comparison logic
Check if current node's value is smaller than stored; if yes, replace it in the map.Final Answer:
Store the node with the smallest value for each horizontal distance, updating if a smaller value is found -> Option DQuick Check:
Keep smallest value per horizontal distance [OK]
- Ignoring node values when duplicates occur
- Using last node instead of smallest value
- Changing traversal order instead of map logic
Ready to prove it?
Pass the test and this pattern moves unknown
