题目
给你二叉树的根结点 root ,请你设计算法计算二叉树的垂序遍历 序列。
对位于 (row, col) 的每个结点而言,其左右子结点分别位于 (row + 1, col - 1) 和 (row + 1, col + 1) 。树的根结点位于 (0, 0) 。
二叉树的 垂序遍历 从最左边的列开始直到最右边的列结束,按列索引每一列上的所有结点,形成一个按出现位置从上到下排序的有序列表。如果同行同列上有多个结点,则按结点的值从小到大进行排序。
返回二叉树的 垂序遍历 序列。


解析
// 怎么递归?
// 深度遍历每个节点,从根节点往下一层传递行号和列号
// 其中左子树行号为父节点行号+1,列号-1;右子树行号为父节点行号+1,列号+1
// 设置一个Map存储深度遍历的节点,键为列号,值为该列的 [行号, 节点值] 列表。
// DFS 时将节点添加到对应列的列表中,最后按列排序、每列内按行排序。
// 按列号从小到大,遍历map中每一个列号键对应的 [行号, 节点值] 值列表:
// 对值列表中的每个元素 [行号, 节点值] ,先按行号从小到大,行号相同再按节点值按从小到大排序
// 将 [行号, 节点值] 列表中的节点值取出构成一个新列表,将列表放到答案列表里
// 最后返回答案列表。
答案
javascript
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number[][]}
*/
var verticalTraversal = function(root) {
let res = [];
const map = new Map();
function dfs(node, row, col) {
if(node === null) return;
let list = map.get(col) || [];
list.push([row, node.val]);
map.set(col, list);
dfs(node.left, row + 1, col - 1);
dfs(node.right, row + 1, col + 1);
}
dfs(root, 0, 0);
const cols = Array.from(map.keys()).sort((a, b) => a - b);
for (const col of cols) {
const nodes = map.get(col);
nodes.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
// 先按行号,行号相同按值
const values = nodes.map(node => node[1]);
res.push(values);
}
return res;
};
复杂度分析
时间复杂度:O(nlogn),其中 n 为二叉树的节点个数。瓶颈在排序上。
空间复杂度:O(n)。
作者:灵茶山艾府
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
