Given the root of a binary tree, return its vertical order traversal.
Assign each node a position (row, col): the root is (0, 0), and a node at (row, col) has its left child at (row + 1, col - 1) and its right child at (row + 1, col + 1). Group nodes by column from left to right. Within a column, order nodes by row (top to bottom); if two nodes share the same row and column, order them by value (smaller first).
The tree is given in level-order (breadth-first), using null for missing children.
Input: root = [3, 9, 20, null, null, 15, 7] Output: [[9], [3, 15], [20], [7]] Columns -1, 0, 1, 2. Column 0 holds 3 (row 0) then 15 (row 2).
Input: root = [1, 2, 3, 4, 5, 6, 7] Output: [[4], [2], [1, 5, 6], [3], [7]] In column 0, nodes 5 and 6 share row 2, so they are ordered by value: 5 then 6.
- The number of nodes is in the range [0, 1000] - 0 <= Node.val <= 1000
Each node gets a (row, col) coordinate — left decrements the column, right increments it, and both increase the row. The output groups nodes by column (left to right), and inside a column sorts by row, breaking ties by value. So: record (col, row, value) for every node and sort — the tie-break on value is the detail that trips people up.
“How are same-position nodes ordered?”
Two nodes at the same (row, col) are ordered by value, smaller first.
“Column order?”
Left to right, i.e. most negative column first.
Each node has a (row, col); I collect (col, row, value) triples for all nodes.
Sorting by column, then row, then value and grouping by column gives the answer — the value tie-break is the subtle part.
Worked example — tree [3, 9, 20, null, null, 15, 7]
col -1: 9 col 0: 3, 15 col 1: 20 col 2: 7 (15 and 3 share col 0 but different rows: 3 at row 0, 15 at row 2) result: [[9], [3, 15], [20], [7]]
Column groups the output; row orders within a column.
Two nodes at the same (row, col) are ordered by value — the rule that makes this harder than the views.
Collect (col, row, value) triples and sort by all three keys; O(n log n).
| DFS collect + global sort | BFS + per-column sort | |
|---|---|---|
| Idea | One sort of all (col,row,val) triples | Bucket by col, sort each by (row,val) |
| Time | O(n log n) | O(n log n) |
| Space | O(n) | O(n) |
Both sort on the same keys; grouping order is identical. Full code is in the Approaches selector below.
Key takeaway
Assign (row, col) coordinates, record (col, row, value) per node, and sort by column then row then value. Group by column. O(n log n) — the value tie-break is the crux.
dfs(node, row, col): record (col, row, val); recurse (row+1, col-1) and (row+1, col+1) sort triples by (col, row, val); group by col