{x}
blog image

Vertical Order Traversal of a Binary Tree

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.

 

Example 1:

Input: root = [3,9,20,null,null,15,7]
Output: [[9],[3,15],[20],[7]]
Explanation:
Column -1: Only node 9 is in this column.
Column 0: Nodes 3 and 15 are in this column in that order from top to bottom.
Column 1: Only node 20 is in this column.
Column 2: Only node 7 is in this column.

Example 2:

Input: root = [1,2,3,4,5,6,7]
Output: [[4],[2],[1,5,6],[3],[7]]
Explanation:
Column -2: Only node 4 is in this column.
Column -1: Only node 2 is in this column.
Column 0: Nodes 1, 5, and 6 are in this column.
          1 is at the top, so it comes first.
          5 and 6 are at the same position (2, 0), so we order them by their value, 5 before 6.
Column 1: Only node 3 is in this column.
Column 2: Only node 7 is in this column.

Example 3:

Input: root = [1,2,3,4,6,5,7]
Output: [[4],[2],[1,5,6],[3],[7]]
Explanation:
This case is the exact same as example 2, but with nodes 5 and 6 swapped.
Note that the solution remains the same since 5 and 6 are in the same location and should be ordered by their values.

 

Constraints:

  • The number of nodes in the tree is in the range [1, 1000].
  • 0 <= Node.val <= 1000

Solution Explanation: Vertical Order Traversal of a Binary Tree

This problem requires traversing a binary tree and returning its vertical order traversal. The vertical order is determined by the column index of each node, where the root is at column 0, left children decrement the column index, and right children increment it. Nodes at the same column and row are sorted by their values.

Approach: Depth-First Search (DFS) and Sorting

This approach uses a Depth-First Search (DFS) to traverse the tree and collect node information. For each node, we record its column index, row index, and value. We then sort this collected data to arrange nodes according to their vertical order.

1. DFS Traversal:

A recursive DFS function visits each node. It takes the current node, row index (i), and column index (j) as input. For each node:

  • It appends a tuple/array (j, i, node.val) to a list nodes. This tuple represents the column, row, and value of the node.
  • It recursively calls itself for the left child (i + 1, j - 1) and right child (i + 1, j + 1).

2. Sorting:

After the DFS traversal, the nodes list contains all nodes' information. We sort this list using a custom comparator (or sort function with appropriate key) based on the following order:

  1. Column index (j) (primary key)
  2. Row index (i) (secondary key)
  3. Node value (node.val) (tertiary key)

This ensures that nodes are sorted correctly within each column and row.

3. Grouping by Column:

Finally, we iterate through the sorted nodes list. We create a new list ans (result) to store the vertical traversal. As we iterate, we check if the current node's column index is different from the previous one. If it's different, it means we're starting a new column, so we append an empty list to ans. Then, we add the current node's value to the last list in ans (the current column's list).

Time and Space Complexity

  • Time Complexity: The DFS traversal takes O(N) time, where N is the number of nodes. The sorting step takes O(N log N) time in the worst case. Therefore, the overall time complexity is dominated by sorting, resulting in O(N log N).
  • Space Complexity: The nodes list stores node information, requiring O(N) space. The recursion stack in DFS also takes O(H) space in the worst case, where H is the height of the tree (H can be N in a skewed tree). The ans list also takes O(N) space. Therefore, the overall space complexity is O(N).

Code Implementation (Python)

from typing import List, Optional
 
# Definition for a binary tree node.
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
 
class Solution:
    def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
        nodes = []
 
        def dfs(node, row, col):
            if node:
                nodes.append((col, row, node.val))
                dfs(node.left, row + 1, col - 1)
                dfs(node.right, row + 1, col + 1)
 
        dfs(root, 0, 0)
        nodes.sort()  # Sorts by column, row, then value
 
        result = []
        current_col = -float('inf')  # Initialize with negative infinity
        current_list = []
 
        for col, row, val in nodes:
            if col != current_col:
                if current_list: # if current list isn't empty, add it to result
                    result.append(current_list)
                current_col = col
                current_list = [val]
            else:
                current_list.append(val)
        
        if current_list:  # Add the last column's list
            result.append(current_list)
 
        return result
 

The code in other languages (Java, C++, Go, TypeScript) follows a similar structure, employing DFS, sorting, and column-wise grouping. The specific syntax and data structures might differ, but the core logic remains the same.