📜  树的垂直锯齿形遍历(1)

📅  最后修改于: 2023-12-03 14:55:38.665000             🧑  作者: Mango

树的垂直锯齿形遍历

在二叉树中,树的垂直锯齿形遍历将树从左到右的任何路径上具有相同垂直坐标的节点分组。也就是说,两个节点在同一行和同一列,如果它们位于树中的不同深度,则它们会被归为不同的组。以下是树的垂直锯齿形遍历的示例。

   3
  / \
 9  20
    / \
   15  7

可以被分为以下的组:

[
  [9],
  [3,15],
  [20],
  [7]
]
解决方法

可以通过深度优先遍历或广度优先遍历来实现树的垂直锯齿形遍历。

方法一:深度优先遍历

遍历树的时候,在遍历的过程中维护一个映射,用于记录相同横坐标的节点。然后进行 DFS 遍历,并使用此映射来获取垂直层数和节点的值。最后将结果从映射表中提取出来即可。

def verticalTraversal(root):
    # 定义一个映射表,键为横坐标,值为这些横坐标对应的节点值列表。
    mapping = collections.defaultdict(list)

    # dfs函数。pos为当前节点的横坐标,level为当前节点的纵坐标。
    def dfs(node, pos, level):

        # 将当前节点的值添加到该横坐标对应的节点值列表上。
        mapping[pos].append((level, node.val))

        # 将左右子节点加入遍历。
        if node.left:
            dfs(node.left, pos - 1, level + 1)
        if node.right:
            dfs(node.right, pos + 1, level + 1)

    # 开始 DFS 遍历。
    dfs(root, 0, 0)

    # 根据横坐标的排序返回遍历的结果。
    return [
        [val for level, val in sorted(mapping[pos])]
        for pos in sorted(mapping)
    ]
方法二:广度优先遍历

可以将节点和节点所在的位置一起保存在一个元组中,并将这些元组添加到一个队列中。因为队列是先进先出的,所以在得到具有相同横坐标的所有节点时,它们的位置是已排序的。

def verticalTraversal(root):
    mapping = collections.defaultdict(list)

    # 将节点添加到队列中。除了节点,我们还需稍稍调整坐标点,以及它们相对于根节点的距离。我们将根节点视为位于(0, 0)。
    queue = [(root, 0, 0)]

    # bfs遍历。
    while queue:
        node, x, y = queue.pop(0)
        mapping[x].append((y, node.val))
        if node.left:
            queue.append((node.left, x-1, y+1))
        if node.right:
            queue.append((node.right, x+1, y+1))

    # 根据坐标的顺序返回遍历结果。
    return [
        [val for y, val in sorted(mapping[x])]
        for x in sorted(mapping)
    ]
总结

在二叉树的垂直锯齿形遍历中,可以使用深度优先遍历或广度优先遍历来实现。在进行遍历的过程中,我们维护一个映射表(或字典),用于记录相同横坐标的节点。最后,我们按照坐标的顺序获取节点的值,并将结果返回给用户。