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

输入:root = [3,9,20,null,null,15,7] 输出:[[9],[3,15],[20],[7]] 解释: 列 -1 :只有结点 9 在此列中。 列 0 :只有结点 3 和 15 在此列中,按从上到下顺序。 列 1 :只有结点 20 在此列中。 列 2 :只有结点 7 在此列中。
示例 2:

输入:root = [1,2,3,4,5,6,7] 输出:[[4],[2],[1,5,6],[3],[7]] 解释: 列 -2 :只有结点 4 在此列中。 列 -1 :只有结点 2 在此列中。 列 0 :结点 1 、5 和 6 都在此列中。 1 在上面,所以它出现在前面。 5 和 6 位置都是 (2, 0) ,所以按值从小到大排序,5 在 6 的前面。 列 1 :只有结点 3 在此列中。 列 2 :只有结点 7 在此列中。
示例 3:

输入:root = [1,2,3,4,6,5,7] 输出:[[4],[2],[1,5,6],[3],[7]] 解释: 这个示例实际上与示例 2 完全相同,只是结点 5 和 6 在树中的位置发生了交换。 因为 5 和 6 的位置仍然相同,所以答案保持不变,仍然按值从小到大排序。
提示:
- 树中结点数目总数在范围
[1, 1000]
内 0 <= Node.val <= 1000
代码结果
运行时间: 16 ms, 内存: 16.3 MB
/*
思路:
1. 使用DFS遍历二叉树,每个节点跟踪其行(row)和列(col)。
2. 使用Map存储列索引到节点值的映射,列索引作为键,值是一个包含(row, node.val)的List。
3. 对每个节点,插入到相应列索引的List中。
4. 遍历Map的每个条目,提取节点值,并按(row, node.val)排序,最后使用Stream进行处理。
*/
import java.util.*;
import java.util.stream.Collectors;
public class VerticalOrderTraversalStream {
static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int val) { this.val = val; }
}
public List<List<Integer>> verticalTraversal(TreeNode root) {
Map<Integer, List<int[]>> map = new HashMap<>();
dfs(root, 0, 0, map);
return map.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.map(entry -> entry.getValue().stream()
.sorted((a, b) -> a[0] == b[0] ? a[1] - b[1] : a[0] - b[0])
.map(a -> a[1])
.collect(Collectors.toList()))
.collect(Collectors.toList());
}
private void dfs(TreeNode node, int row, int col, Map<Integer, List<int[]>> map) {
if (node == null) return;
map.computeIfAbsent(col, k -> new ArrayList<>()).add(new int[]{row, node.val});
dfs(node.left, row + 1, col - 1, map);
dfs(node.right, row + 1, col + 1, map);
}
}
解释
方法:
本题解使用深度优先搜索(DFS)遍历二叉树,将每个节点的列、行、值信息存储到一个列表中。然后对列表进行排序,按照列、行、值的顺序进行排序。最后遍历排序后的列表,将相同列的节点值放入同一个子列表中,最终得到按垂序遍历顺序排列的结果列表。
时间复杂度:
O(nlogn)
空间复杂度:
O(n + w)
代码细节讲解
🦆
在深度优先搜索(DFS)中,您是如何处理不同的分支以确保列和行的正确性?
▷🦆
您是如何确定排序时列、行和值的优先级的?为什么选择这种特定的排序顺序?
▷🦆
代码中使用了`nodes.sort()`直接对元组进行排序。在存在多个节点在同一行同一列的情况下,这种排序方式是否能保证按节点值的升序排列?
▷🦆
在遍历排序后的列表生成结果列表时,您如何处理和区分不同列的节点?
▷