LeetCode987-二叉树的垂序遍历

题目链接

英文链接:https://leetcode.com/problems/vertical-order-traversal-of-a-binary-tree/

中文链接:https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree/

题目详述

给定二叉树,按垂序遍历返回其结点值。

对位于 (X, Y) 的每个结点而言,其左右子结点分别位于 (X-1, Y-1) 和 (X+1, Y-1)。

把一条垂线从 X = -infinity 移动到 X = +infinity ,每当该垂线与结点接触时,我们按从上到下的顺序报告结点的值( Y 坐标递减)。

如果两个结点位置相同,则首先报告的结点值较小。

按 X 坐标顺序返回非空报告的列表。每个报告都有一个结点值列表。

示例 1:

1
2
3
4
5
6
7
8
输入:[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
输入:[1,2,3,4,5,6,7]
输出:[[4],[2],[1,5,6],[3],[7]]
解释:
根据给定的方案,值为 5 和 6 的两个结点出现在同一位置。
然而,在报告 "[1,5,6]" 中,结点值 5 排在前面,因为 5 小于 6。

提示:

  1. 树的结点数介于 1 和 1000 之间。
  2. 每个结点值介于 0 和 1000 之间。

题目详解

  • 首先遍历得到所有带坐标的结点。
  • 然后对结点进行排序,按照 x 从小到大、y 从大到小、结点值从小到大的顺序。
  • 最后遍历得到按 X 坐标顺序返回非空报告的列表。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class LeetCode_00987 {

public List<List<Integer>> verticalTraversal(TreeNode root) {
List<int[]> list = new ArrayList<>();
dfs(root, 0, 0, list);
list.sort(new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
if (o1[0] != o2[0]) return Integer.compare(o1[0], o2[0]);
if (o1[1] != o2[1]) return Integer.compare(o2[1], o1[1]);
return Integer.compare(o1[2], o2[2]);
}
});
List<List<Integer>> res = new ArrayList<>();
int preX = 1;
for (int[] cur : list) {
if (preX != cur[0]) {
res.add(new ArrayList<>());
preX = cur[0];
}
res.get(res.size() - 1).add(cur[2]);
}
return res;
}

private void dfs(TreeNode root, int x, int y, List<int[]> list) {
if (root == null) {
return;
}
list.add(new int[]{x, y, root.val});
dfs(root.left, x - 1, y - 1, list);
dfs(root.right, x + 1, y - 1, list);
}
}