Algorithm

Binary Tree Top/Bottom View

Trees Pattern

Binary Tree Top/Bottom View

Draw the tree so the root sits at horizontal position 0, every left step moves one unit left and every right step one unit right. Nodes sharing a position line up in the same vertical column. The top view is the shallowest node of each column; the bottom view is the deepest. Return the chosen values ordered by column from leftmost to rightmost. An empty tree returns an empty list.

CONSTRAINTS
  • The number of nodes is in the range [0, 100]
  • -100 <= Node.val <= 100
  • Columns are ordered left to right in the output
  • Exactly one value per non-empty column
EXAMPLE 1
Input: root = [1,2,3,4,5,6,7], top view
Output: [4,2,1,3,7]
Columns -2 through 2. Column 0 holds the root along with 5 and 6 from deeper down; the root is shallowest, so it is the one seen from above and the other two are hidden beneath it.
EXAMPLE 2
Input: root = [1,2,3,4,5,6,7], bottom view
Output: [4,5,6,3,7]
Same columns, opposite rule. Column 0 now shows the deepest node in it. Both 5 and 6 sit at that depth, and the convention is that the later one in left-to-right order wins, so 6 is reported.
EXAMPLE 3
Input: root = [1,2,3,null,4], top view
Output: [2,1,3]
4 is the right child of 2, so its left step and right step cancel and it lands back in column 0 alongside the root. The root is shallower, so 4 is hidden and contributes nothing to the view.
EXAMPLE 4
Input: root = [1], top view
Output: [1]
One node, one column, visible from every direction.
How is the horizontal position defined?
The root is 0; a left child is its parent minus 1, a right child plus 1. Nodes from completely different subtrees can share a position, which is the entire difficulty.
What if two nodes in a column sit at the same depth?
It can happen — a right-then-left path and a left-then-right path both return to the same column at the same depth. Ask the interviewer; the common convention is that the one encountered later in left-to-right order wins for the bottom view, while the top view is unaffected since a shallower node already claimed the column.
Must the output be sorted by column?
Yes, leftmost column first. Positions can be negative, so this is a genuine ordering step, not just the traversal order.
Can a depth-first traversal be used?
For the top view it is risky: depth-first can reach a column via a deep left path before a shallow right one, so you must compare depths explicitly rather than trusting arrival order. Breadth-first makes arrival order equal depth order and removes the problem.

Both views ask the same question with different tie-breaks: group the nodes into vertical columns, then pick one node from each column — the highest for the top view, the lowest for the bottom view.

The word "column" is what needs defining, because a tree's node has no built-in horizontal coordinate. Give it one: the root sits at 0, stepping left subtracts 1, stepping right adds 1. Two nodes with the same number line up vertically no matter how far apart they are in the tree. This is the same move as in Maximum Width of Binary Tree — invent a coordinate so a spatial question becomes arithmetic — except that there the position had to distinguish every seat, while here left and right steps deliberately cancel so that different subtrees can share a column.

That cancellation is the source of all the difficulty. A node reached by going left-then-right ends up in the same column as the root, so a column can gather nodes from wildly different parts of the tree, and there is no way to walk a column directly.

Group first, then pick

So collect rather than search. Walk the whole tree, and as each node is visited, file it under its column number in a map from position to value. Every node is filed exactly once; the only question is what happens when a column already has an entry.

- Top view: keep the first node filed in a column and ignore all later ones.
- Bottom view: overwrite, so the last node filed wins.

For those rules to be correct, "first filed" must mean "shallowest." A breadth-first walk gives exactly that: it visits all of depth 0, then all of depth 1, and so on, so arrival order is depth order. Under a depth-first walk it is not — a node five levels down the left subtree is visited long before the root's right child — and the top-view rule would silently pick the wrong node. Breadth-first is not a stylistic choice here; it is what makes the tie-break sound.

python
if root is None: return []
col = {}                                   # position -> chosen value
queue = deque([(root, 0)])                 # each entry: a node and its column
while queue:
    node, x = queue.popleft()
    if is_top:
        if x not in col:                   # first arrival = shallowest = visible from above
            col[x] = node.val
    else:
        col[x] = node.val                  # last arrival = deepest = visible from below
    if node.left:  queue.append((node.left,  x - 1))
    if node.right: queue.append((node.right, x + 1))
return [col[x] for x in sorted(col)]       # columns, leftmost first
Crucial Notethe final sorted is not optional and not free. The map's keys are column numbers that may be negative and arrive in no particular order, so the output must be ordered explicitly — forgetting this produces the right values in an arbitrary arrangement, which is a hard bug to spot on small symmetric examples. Sorting costs O(K log K) for K columns; if that matters, track the smallest and largest column seen during the walk and read the map out from min to max, which is O(K) since every column between two occupied columns is itself occupied.
Worked example:root 1, children 2 and 3; 2 has children 4 and 5; 3 has children 6 and 7. Top view
- Visit 1 at column 0. Column 0 is empty → record 1. Enqueue 2 at -1, 3 at +1.
- Visit 2 at -1 → record 2. Enqueue 4 at -2, 5 at 0.
- Visit 3 at +1 → record 3. Enqueue 6 at 0, 7 at +2.
- Visit 4 at -2 → record 4.
- Visit 5 at column 0 — already taken by the root, which is one level shallower. Skipped.
- Visit 6 at column 0 — also taken. Skipped.
- Visit 7 at +2 → record 7.
- Columns sorted: -2, -1, 0, 1, 2 → [4, 2, 1, 3, 7].

Now the bottom view on the same tree. Every visit overwrites, so column 0 is claimed by 1, then overwritten by 5, then by 6 — leaving 6, the last of the two deepest nodes in that column. The result is [4, 5, 6, 3, 7]. Note that 5 and 6 are at the same depth in the same column; the queue's left-to-right order is what makes 6 the winner, and this is exactly the ambiguity worth raising with an interviewer.

Cost, and the pattern

Every node is enqueued and dequeued once with constant work: O(N) for the walk. Sorting the columns adds O(K log K) where K is the number of distinct columns, at most N. Space is O(N) for the map plus O(W) for the queue.

The skeleton to lift from this problem is coordinate, collect, resolve: give each node a coordinate that captures the geometry the question cares about, group nodes by it, then apply a tie-break within each group. Once framed that way, a whole family follows immediately — top view keeps the minimum depth per column, bottom view the maximum, and Vertical Order Traversal, coming next, keeps all of them sorted within each column, which is why it needs a more careful tie-break than either view here.

Interactive Strategy Visualization

Vertical Projection

Toggle between Top and Bottom views

Column projection

Project every node onto a horizontal x-axis (HD).

top logic
Keep FIRST node encountered at each HD (Shallowest).
* HD = Horizontal Distance relative to root (0).
0TOP-1+10
O(N) BFS Column Map + O(K log K) Column Sort
O(N) Time By Tracking Min And Max Column