Given the root
of a binary tree, return the vertical order traversal of its nodes' values. (i.e., from top to bottom, column by column).
If two nodes are in the same row and column, the order should be from left to right.
Example 1:
Input: root = [3,9,20,null,null,15,7] Output: [[9],[3,15],[20],[7]]
Example 2:
Input: root = [3,9,8,4,0,1,7] Output: [[4],[9],[3,0,1],[8],[7]]
Example 3:
Input: root = [3,9,8,4,0,1,7,null,null,null,2,5] Output: [[4],[9,5],[3,0,1],[8,2],[7]]
Constraints:
- The number of nodes in the tree is in the range
[0, 100]
. -100 <= Node.val <= 100
题目要求以垂直顺序遍历二叉树,就是从顶到底,处于相同列的节点放到一个数组中,最后结果就是由所有列数组组成的一个二维数组。关于列的定义:假设一个节点的列号是col,那么它的左子节点为col-1,右子节点的列号就为col+1。
由于我们对水平顺序遍历算法很熟悉,因此本题就是在水平顺序遍历的基础上,给每个节点分配一个列号,这样就可以把具有相同列号的节点值放在一起。首先规定根节点的列号为0,然后以水平顺序遍历,这样处在根节点以左的节点列号为负值,从根节点开始每往左一个位置列号就减1;处在根节点右边的节点列号为正,从根节点开始每往右一个位置列号就加1;与根节点处于同一列的节点列号为0。为了便于处理,可以一个用二维数组存放根节点及其左边所有列,数组的索引就是列号的相反数(即列号为0, -1, -2, ...对应数组索引为0, 1, 2, ...),再用一个二维数组存放根节点右边所有列(由于列号为0归到了左边数组,因此列号为1, 2, 3, ...对应数组索引为0, 1, 2, ...)。这样在做水平遍历时,就可以根据列号实时把节点放入左边或右边数组对应的位置上。对于左边数组,每当列号的绝对值等于数组总个数时就新增一列;对于右边数组,每当列号大于数组总个数就新增一列。
def verticalOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
if not root:
return []
llist, rlist = [], []
lindex, rindex = 0, 1
q = deque([(root, 0)])
while q:
n = len(q)
for i in range(n):
node, index = q.popleft()
if index <= 0:
if len(llist) > -index:
llist[-index].append(node.val)
else:
llist.append([node.val])
else:
if len(rlist) > index - 1:
rlist[index - 1].append(node.val)
else:
rlist.append([node.val])
if node.left:
q.append((node.left, index - 1))
if node.right:
q.append((node.right, index + 1))
llist.reverse()
return llist + rlist