Binary Tree Vertical Order Traversal

题目描述

Given a binary tree, return the vertical order traversal of its nodes' values. (ie, from top to bottom, column by column).

Examples: Given binary tree [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

return its vertical order traversal as:

[
  [9],
  [3,15],
  [20],
  [7]
]

解题方法

第一次看到估计懵B, 拿到题目先画几个例子,找实例,clarify问题永远是最重要的!

基本上二叉树的问题,类型就是recursive, DFS, BFS,blablabla。这个题目应该也差不多, recursive打印肯定不行,但是遍历整个树找找感觉还是可以的。我们做过level order traversal,这里是按照列的方式traversal,那么如何知道当前node的列数呢?

我们可以自己define,比如例子里面

  • 第一列 9
  • 第二列 3, 15
  • 第三列 20
  • 第四列 7

暂时是这样,但是并没有太大帮助,我们又可以发现root 3 和node 15是同一列的,而 root到15的路径是怎样的呢?root -> 右 -> 左 -> 15,发现左右抵消了。所以可以进一步 define列数,向左就减1,向右就加1。

到这里基本上就应该知道怎么做了,根据这个定义求出所有node的“列数”,然后将相同 列数的放到同一个array里。

方法1

只用O(1)的space,找出列数的上下限,然后再遍历找出分别对应当前列数的node

time complexity: O(w * n), w是列数的范围,worst case是O(n^2)

方法2

第一种方法要不断地遍历整个树,肯定不是optimal的,使用O(n)的space建一个hashtable, key:value是 {列:[node1, node2, node2]},这样遍历一遍,然后打印就可以了。

在leetcode上还要求同一列的要从上往下打印,所以还要记录下行数,将行数和node一起存在 一个tuple里就好了

Solution

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

# h_d means horizontal distance
# get h_d for each node, and save into hashmap
# left means h_d - 1, right means h_d + 1

class Solution(object):

    def __init__(self):
        self.min_hd = sys.maxint
        self.max_hd = -sys.maxint

    def verticalOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        if not root:
            return []

        d_n_map = {}
        result = []
        self.getNodeHD(root, 0, d_n_map, 0)

        for i in range(self.min_hd, self.max_hd+1):
            cur_list = d_n_map[i]
            # 根据vertical distance sort
            cur_list = sorted(cur_list, key=lambda n: n[1])
            new_list = map(lambda n: n[0], cur_list) # map function
            result.append(new_list)

        return result

    def getNodeHD(self, root, hd, d_n_map, vd):
        if not root:
            return
        if hd < self.min_hd:
            self.min_hd = hd
        if hd > self.max_hd:
            self.max_hd = hd
        if hd in d_n_map:
            d_n_map[hd].append((root.val, vd))
        else:
            d_n_map[hd] = [(root.val, vd)]

        self.getNodeHD(root.left, hd-1, d_n_map, vd+1)
        self.getNodeHD(root.right, hd+1, d_n_map, vd+1)

Reference