Vertical Order Traversal
Group nodes by column (left child −1, right +1); within a column sort by row, ties by value.
Open on LeetCode ↗Intuition
Every node has a 2-D coordinate: (row, col) assigned by the traversal. Collect (col, row, val) triples with any DFS, then sort — the whole problem is coordinates plus a well-defined ordering.
Column index decreases left and increases right; row index increases downward. Collecting (row, value) per column and sorting handles the tie-break rule — same column and same row means order by value. Recording both coordinates up front is what lets one sort resolve every tie correctly.
Approach
Assign coordinates
Root (0,0); left child (row+1, col−1); right child (row+1, col+1). One DFS collects all triples.
Group by column
Bucket triples by col (a dict), columns read left to right — sort the keys.
Order inside a column
Sort each bucket by (row, val) — the value tiebreak is the spec's subtle requirement.
Solution & live demo
Common pitfalls
Ignoring the value tie-break
cols[c].append(node.val) # ... later: cols[c] stays in DFS order
cols[c].append((r, node.val)) # ... sorted(cols[c])
Two nodes can share a column and a row, and the problem demands the smaller value first. Storing only values leaves them in traversal order, which is arbitrary with respect to that rule.
Using BFS and assuming row order is enough
# BFS, append in visit order
cols[c].append((r, node.val)) sorted(cols[c])
BFS does give correct row ordering, but it still can't break same-cell ties by value without an extra sort. Since a sort is needed anyway, DFS with explicit coordinates is simpler and equally correct.
Iterating the column dict without sorting keys
return [cols[c] for c in cols]
return [... for c in sorted(cols)]
Dict iteration order reflects insertion, which follows the traversal, not the left-to-right column order the output requires. The keys must be sorted numerically.
Edge cases
The value tiebreak orders them — required by the problem.
Columns spread −n..0 or 0..n; dict handles sparse keys.