Vertical Order Traversal
Place the root at coordinates (row 0, column 0); a left child is one row down and one column left, a right child one row down and one column right. Group every node by column and return the groups ordered from the leftmost column to the rightmost. Within a column, nodes are ordered by row, top to bottom; and if two nodes share both row and column, they are ordered by value, smallest first. An empty tree returns an empty list.
- The number of nodes is in the range [0, 1000]
- 0 <= Node.val <= 1000
- Columns are output left to right; within a column, rows run top to bottom
- Nodes sharing a row and column are ordered by value ascending
root = [3,9,20,null,null,15,7][[9],[3,15],[20],[7]]root = [1,2,3,4,5,6,7][[4],[2],[1,5,6],[3],[7]]root = [3,1,4,0,2,2,null][[0],[1],[3,2,2],[4]]root = [1][[1]]This extends the column idea from Binary Tree Top/Bottom View. There, each column reported a single node — the shallowest or the deepest. Here every node is reported, so a column becomes an ordered list, and the interesting work moves into deciding that order.
Each node gets two coordinates: a column x (root 0, left child x - 1, right child x + 1) and a row y (root 0, both children y + 1). The output is then: group by x, sort the groups by x, and within each group sort by y, breaking ties by value.
It is tempting to reach straight for the level-by-level walk and assume it delivers the right order for free. A breadth-first walk does visit rows in increasing order, so nodes land in each column already sorted by row — that much is genuinely free.
The trap is the tie. Two nodes can share a column and a row: in a full tree of seven nodes, node 2's right child and node 3's left child both sit in column 0 at row 2. A left-to-right breadth-first walk visits them in tree order, which is not the required order. The problem says these must be sorted by value, and value has no relationship at all to where a node sits. No traversal order can produce that; it has to be imposed afterwards.
So walk the tree in any order at all — depth-first is fine, and simpler here — recording a triple (x, y, value) for every node. Then sort the whole collection by x, then y, then value, and cut it into groups wherever x changes. That single sort satisfies all three ordering rules at once, because sorting by a tuple compares the first component first and only consults the later ones on ties — exactly the precedence the problem describes.
nodes = []
def walk(node, x, y):
if node is None: return
nodes.append((x, y, node.val)) # column, row, value
walk(node.left, x - 1, y + 1)
walk(node.right, x + 1, y + 1)
walk(root, 0, 0)
nodes.sort() # by x, then y, then value — in that priority
out = []
for x, _, val in nodes:
if not out or x != prev_x: # a new column starts a new group
out.append([])
prev_x = x
out[-1].append(val)
return outNote 5 and 6 — they land on the identical spot, arriving from opposite subtrees, because 5 went left-then-right and 6 went right-then-left.
Sorted by (column, row, value):
- (-2, 2, 4)
- (-1, 1, 2)
- (0, 0, 1), then (0, 2, 5), then (0, 2, 6) — the first two are separated by row; the last two tie on row and are separated by value.
- (1, 1, 3)
- (2, 2, 7)
Cutting on column changes gives [[4], [2], [1, 5, 6], [3], [7]]. Had 5 and 6 held the values 9 and 5 instead, the column would read [1, 5, 9] — the values decide, not which subtree the node came from.
The walk is O(N); the sort dominates at O(N log N) time, with O(N) space for the collected triples. It is possible to avoid the global sort by bucketing into a map keyed by column and sorting each column separately, but the worst case is unchanged when one column holds most of the nodes.
The lesson is a small but useful piece of judgement: check whether the required ordering is entirely determined by structure, and if it is not, stop trying to be clever with the traversal. Top and bottom views could be resolved by arrival order because depth alone decided the winner. This problem's value tie-break lives outside the structure, so an explicit sort is not a failure to find the elegant solution — it is the correct one. Recognising which side of that line a problem falls on saves a lot of debugging.
Vertical Batching
Full Spectrum Traversal Strategy
Note: For nodes at the same HD and Level, Vertical Order traditionally sorts them by value.