Top View of Binary Tree asks what you would see if you floated directly above the tree and looked straight down. It is a clean lesson in pairing a level-order BFS with a small piece of bookkeeping — a horizontal distance — to decide which nodes are visible.
Problem. Given the root of a binary tree, return the top view: for each vertical column of nodes, the single node nearest the top, read from the leftmost column to the rightmost.
Example: the tree with root 1, children 2 (left) and 3 (right), and grandchildren 4, 5 under 2
and 6, 7 under 3, has top view [4, 2, 1, 3, 7].
The slow way first
You could try to reason column by column, walking down each vertical line and keeping the first node — but a tree is not laid out in columns, so there is no easy way to "walk a column." You would end up doing a full traversal anyway, then sorting and grouping by position, which is fiddly and easy to get wrong.
The better question: can I give each node a coordinate that says which column it belongs to, then let a single traversal fill in the answer? Yes — that coordinate is the horizontal distance.
The idea: horizontal distance plus first-come-first-served
Give the root horizontal distance hd = 0. Whenever you move to a left child, subtract 1; to a right child, add 1. Nodes that end up with the same hd sit in the same vertical column.
Now run a BFS (level order). Because BFS visits shallower nodes before deeper ones, the first node you reach at any given hd is the highest node in that column — exactly the one visible from above. Keep a map hd -> value and only write when the hd is new.
The key insight: BFS order guarantees top-most-first, so a simple "write only if this hd is new" rule is all the bookkeeping you need.
Walk through it
Step through the animation. Each node shows its hd tag. BFS pops nodes level by level; the top map fills as new columns appear. When 5 and 6 come up — both hd 0 — the column is already owned by the root 1, so they are hidden behind it and skipped. At the end, reading the map by hd from left to right gives the answer.
Pseudocode
if tree is empty: return []
top = empty map # horizontal distance -> first value seen
queue = [(root, hd = 0)]
while queue is not empty:
(node, hd) = pop front of queue
if hd is not already a key in top:
top[hd] = node value # first node at this column
if node has left child: enqueue (left, hd - 1)
if node has right child: enqueue (right, hd + 1)
return values of top sorted by hd, left to rightThe Python solution
from collections import deque
def top_view(root):
if not root:
return []
top = {} # hd -> first value seen
queue = deque([(root, 0)]) # (node, hd)
while queue:
node, hd = queue.popleft()
if hd not in top: # first node at this hd
top[hd] = node.val
if node.left: queue.append((node.left, hd - 1))
if node.right: queue.append((node.right, hd + 1))
return [top[hd] for hd in sorted(top)]topmaps a horizontal distance → the first value seen at that distance.queueholds(node, hd)pairs; we seed it with the root athd = 0.queue.popleft()is what makes this BFS — front of the queue, so shallower nodes come out first.if hd not in top:is the whole trick — we record a column only the first time we reach it, and BFS guarantees that first time is the top-most node.- Children inherit
hd - 1(left) andhd + 1(right), so each enqueue places the child in the right column. - The final line reads the map in
hdorder, giving the top view left to right.
Complexity
| Case | Time | Notes |
|---|---|---|
| BFS over all nodes | O(n) (moderate) | each node enqueued and popped once |
| Sort the map by hd | O(k log k) (moderate) | k = number of distinct columns, k <= n |
O(n) (moderate)Each node is visited exactly once, so the traversal is O(n). The final sort touches one entry per column. The map and queue each hold up to O(n) entries.
When this pattern shows up
Any "view" of a tree — top view, bottom view, left/right view, or vertical order traversal — is the same move: tag each node with a horizontal distance, then traverse and resolve ties by a rule. Top view keeps the first node per hd; bottom view keeps the last; vertical order keeps them all.
Use BFS, not DFS, for top view. With DFS you might reach a deeper node in a column before a shallower one in a sibling subtree, so "first seen" would no longer mean "top-most." If you must use DFS, you have to also track depth and keep the node with the smallest depth per hd.
Practice
In the example tree, node 5 has hd 0 and node 6 also has hd 0. Why does neither appear in the top view?
1. What does the horizontal distance (hd) of a node represent?
2. Why does BFS (level order) make this work with a simple first-seen rule?
3. When BFS pops a node whose hd is already in the map, what happens?
4. What is the time complexity of the BFS solution?