987. 二叉树的垂序遍历
给定二叉树,按垂序遍历返回其结点值。
对位于 (X, Y)
的每个结点而言,其左右子结点分别位于 (X-1, Y-1)
和 (X+1, Y-1)
。
把一条垂线从 X = -infinity
移动到 X = +infinity
,每当该垂线与结点接触时,我们按从上到下的顺序报告结点的值( Y
坐标递减)。
如果两个结点位置相同,则首先报告的结点值较小。
按 X
坐标顺序返回非空报告的列表。每个报告都有一个结点值列表。
示例 1:
输入:[3,9,20,null,null,15,7]
输出:[[9],[3,15],[20],[7]]
解释:
在不丧失其普遍性的情况下,我们可以假设根结点位于 (0, 0):
然后,值为 9 的结点出现在 (-1, -1);
值为 3 和 15 的两个结点分别出现在 (0, 0) 和 (0, -2);
值为 20 的结点出现在 (1, -1);
值为 7 的结点出现在 (2, -2)。
示例 2:
输入:[1,2,3,4,5,6,7]
输出:[[4],[2],[1,5,6],[3],[7]]
解释:
根据给定的方案,值为 5 和 6 的两个结点出现在同一位置。
然而,在报告 "[1,5,6]" 中,结点值 5 排在前面,因为 5 小于 6。
提示:
- 树的结点数介于
1
和1000
之间。 - 每个结点值介于
0
和1000
之间。
思路
- 先用BFS 或者 DFS遍历出来
- 然后把遍历出来的数组排序
- 一个个的往数组里面推进去就行了
PS:开始用的BFS遍历出来,然后感觉用inorder可以省去排序这一步,写出来发现还是得排一遍。。。
代码
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @return {number[][]}
*/
var verticalTraversal = function(root) {
let queue = [], list = [];
function dfs(node, x, y) {
if (node != null) {
dfs(node.left, x - 1, y + 1)
list.push({val: node.val, x, y})
dfs(node.right, x + 1, y + 1)
}
}
dfs(root, 0, 0)
list = list.sort((prev, cur) => {
if (prev.x != cur.x) {
return prev.x - cur.x
}
if (prev.y != cur.y) {
return prev.y - cur.y
}
return prev.val - cur.val
})
let res = [[list[0].val]];
for(let i = 1; i < list.length; i++) {
let cur = list[i], pre = list[i - 1];
if (cur.x > pre.x) {
res.push([cur.val])
} else {
let curResItem = res[res.length - 1];
curResItem.push(cur.val)
}
}
return res
};
复杂度分析
时间复杂度 dfs #card=math&code=O%28NlogN%29) + 遍历 #card=math&code=O%28NlogN%29) + 推入 #card=math&code=O%28N%29)
空间复杂度 #card=math&code=O%28N%29)