Language Selection
Choose your preferred programming language
Vertical Order Traversal of Binary Tree
Problem Statement
Given the root of a binary tree, calculate the vertical order traversal of the binary tree.
For each node at position (row, col), its left and right children will be at positions (row + 1, col - 1) and (row + 1, col + 1) respectively. The root of the tree is at (0, 0).
The vertical order traversal of a binary tree is a list of top-to-bottom orderings for each column index starting from the leftmost column and ending on the rightmost column. There may be multiple nodes in the same row and same column. In such a case, sort these nodes by their values.
Return the vertical order traversal of the binary tree.
Input/Output Specifications
- Input: The root of a binary tree where
1 <= number of nodes <= 1000and0 <= Node.val <= 1000 - Output: A list of lists containing node values in vertical order
Constraints
1 <= number of nodes <= 10000 <= Node.val <= 1000
Examples
Example 1:
Input: root = [3,9,20,null,null,15,7]
Output: [[9],[3,15],[20],[7]]
Explanation:
Column -1: Only node 9
Column 0: Nodes 3 and 15 (sorted by value)
Column 1: Only node 20
Column 2: Only node 7
Example 2:
Input: root = [1,2,3,4,5,6,7]
Output: [[4],[2],[1,5,6],[3],[7]]
Solution Approaches
Approach 1: DFS with Coordinate Tracking - Optimal
Algorithm Explanation:
- Use DFS to traverse the tree and assign coordinates to each node
- Store nodes by their column index in a hash map
- For each column, sort nodes by row first, then by value
- Return the result in column order
Implementation:
Python:
from collections import defaultdict
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def verticalTraversal(root):
"""
Vertical order traversal using DFS with coordinate tracking
Time: O(n log n)
Space: O(n)
"""
if not root:
return []
# Dictionary to store nodes by column
column_map = defaultdict(list)
def dfs(node, row, col):
if not node:
return
# Store node with its coordinates
column_map[col].append((row, node.val))
# Traverse left and right children
dfs(node.left, row + 1, col - 1)
dfs(node.right, row + 1, col + 1)
# Start DFS from root
dfs(root, 0, 0)
# Sort columns and build result
result = []
for col in sorted(column_map.keys()):
# Sort nodes in the same column by row, then by value
column_map[col].sort()
result.append([val for row, val in column_map[col]])
return result
Java:
import java.util.*;
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
class Solution {
public List<List<Integer>> verticalTraversal(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();
if (root == null) {
return result;
}
Map<Integer, List<int[]>> columnMap = new HashMap<>();
dfs(root, 0, 0, columnMap);
List<Integer> columns = new ArrayList<>(columnMap.keySet());
Collections.sort(columns);
for (int col : columns) {
List<int[]> nodes = columnMap.get(col);
nodes.sort((a, b) -> {
if (a[0] != b[0]) {
return Integer.compare(a[0], b[0]);
}
return Integer.compare(a[1], b[1]);
});
List<Integer> column = new ArrayList<>();
for (int[] node : nodes) {
column.add(node[1]);
}
result.add(column);
}
return result;
}
private void dfs(TreeNode node, int row, int col, Map<Integer, List<int[]>> columnMap) {
if (node == null) {
return;
}
columnMap.computeIfAbsent(col, k -> new ArrayList<>()).add(new int[]{row, node.val});
dfs(node.left, row + 1, col - 1, columnMap);
dfs(node.right, row + 1, col + 1, columnMap);
}
}
Complexity Analysis:
- Time Complexity: O(n log n) - DFS traversal + sorting
- Space Complexity: O(n) - Hash map and recursion stack
Key Insights
- Coordinate System: Assign (row, col) coordinates to each node
- Column Grouping: Group nodes by their column index
- Sorting: Sort nodes within each column by row, then by value
- Traversal Order: DFS or BFS both work for coordinate assignment
Edge Cases
- Empty Tree: Return empty list
- Single Node: Return single column with one node
- Skewed Tree: Handle left-skewed or right-skewed trees
- Same Column: Multiple nodes in the same column
- Same Row and Column: Sort by value when coordinates are identical
Test Cases
def test_verticalTraversal():
# Test case 1
root1 = TreeNode(3)
root1.left = TreeNode(9)
root1.right = TreeNode(20)
root1.right.left = TreeNode(15)
root1.right.right = TreeNode(7)
assert verticalTraversal(root1) == [[9], [3, 15], [20], [7]]
# Test case 2
root2 = TreeNode(1)
root2.left = TreeNode(2)
root2.right = TreeNode(3)
root2.left.left = TreeNode(4)
root2.left.right = TreeNode(5)
root2.right.left = TreeNode(6)
root2.right.right = TreeNode(7)
assert verticalTraversal(root2) == [[4], [2], [1, 5, 6], [3], [7]]
print("All tests passed!")
test_verticalTraversal()
Follow-up Questions
- Horizontal Order: Traverse horizontally by rows?
- Diagonal Traversal: Traverse diagonally?
- Boundary Traversal: Traverse only boundary nodes?
- Spiral Traversal: Traverse in spiral order?
- Zigzag Traversal: Traverse in zigzag pattern?
Common Mistakes
- Coordinate Assignment: Incorrect row/column assignment
- Sorting Logic: Wrong sorting order within columns
- Column Ordering: Not sorting columns correctly
- Edge Case Handling: Not handling empty tree or single node
- Data Structure: Using wrong data structure for column mapping
Interview Tips
- Start with DFS: Begin with DFS approach
- Explain Coordinates: Describe the coordinate system
- Discuss Sorting: Explain sorting requirements
- Handle Edge Cases: Cover empty tree and special cases
- Code Carefully: Pay attention to coordinate calculations
Concept Explanations
Vertical Order Traversal: A tree traversal method where nodes are grouped by their column index and returned in column order from left to right.
Coordinate System: A system where each node is assigned (row, col) coordinates based on its position in the tree. The root is at (0, 0), left children move to (row+1, col-1), and right children move to (row+1, col+1).
Column Grouping: The process of grouping nodes by their column index to create vertical columns of nodes.
When to Use: Use this pattern when you need to traverse a tree in a specific spatial order, such as vertical, horizontal, or diagonal traversal.