输出二叉树
难度:
标签:
题目描述
给你一棵二叉树的根节点 root
,请你构造一个下标从 0 开始、大小为 m x n
的字符串矩阵 res
,用以表示树的 格式化布局 。构造此格式化布局矩阵需要遵循以下规则:
- 树的 高度 为
height
,矩阵的行数m
应该等于height + 1
。 - 矩阵的列数
n
应该等于2height+1 - 1
。 - 根节点 需要放置在 顶行 的 正中间 ,对应位置为
res[0][(n-1)/2]
。 - 对于放置在矩阵中的每个节点,设对应位置为
res[r][c]
,将其左子节点放置在res[r+1][c-2height-r-1]
,右子节点放置在res[r+1][c+2height-r-1]
。 - 继续这一过程,直到树中的所有节点都妥善放置。
- 任意空单元格都应该包含空字符串
""
。
返回构造得到的矩阵 res
。
示例 1:

输入:root = [1,2] 输出: [["","1",""], ["2","",""]]
示例 2:

输入:root = [1,2,3,null,4] 输出: [["","","","1","","",""], ["","2","","","","3",""], ["","","4","","","",""]]
提示:
- 树中节点数在范围
[1, 210]
内 -99 <= Node.val <= 99
- 树的深度在范围
[1, 10]
内
代码结果
运行时间: 28 ms, 内存: 15.9 MB
/*
* 思路:
* 1. 使用流操作来遍历树,计算高度并构造结果矩阵。
* 2. 利用流的forEach和map方法来简化矩阵的填充操作。
*/
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Solution {
private int getHeight(TreeNode root) {
if (root == null) return 0;
return 1 + Math.max(getHeight(root.left), getHeight(root.right));
}
public List<List<String>> printTree(TreeNode root) {
int height = getHeight(root);
int m = height + 1;
int n = (int) Math.pow(2, height + 1) - 1;
// 初始化结果矩阵
List<List<String>> res = IntStream.range(0, m)
.mapToObj(i -> IntStream.range(0, n)
.mapToObj(j -> "")
.collect(Collectors.toList()))
.collect(Collectors.toList());
fill(res, root, 0, 0, n - 1);
return res;
}
private void fill(List<List<String>> res, TreeNode root, int row, int left, int right) {
if (root == null) return;
int mid = (left + right) / 2;
res.get(row).set(mid, Integer.toString(root.val));
fill(res, root.left, row + 1, left, mid - 1);
fill(res, root.right, row + 1, mid + 1, right);
}
}
解释
方法:
这个题解使用深度优先搜索(DFS)的方式遍历二叉树。首先通过一次 DFS 求出树的高度 height。然后创建大小为 height * (2^height - 1) 的答案矩阵,所有元素初始化为空字符串。接着从根节点开始进行另一次 DFS,在答案矩阵中填入对应节点的值。填入位置根据当前节点的高度以及是左子节点还是右子节点来确定。最后返回填好的答案矩阵即可。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
在计算左右子节点的位置时`c - diff`和`c + diff`,这里的diff是如何计算的,为什么是`2 ** (height - 2 - r)`?
▷🦆
在确定二叉树的高度`height`时,为什么使用`height - 1`来初始化答案矩阵的行数,而不是直接使用`height`?
▷🦆
如何保证在填充答案矩阵时,不会在同一位置重复填充节点值,特别是在具有多个子树分支的复杂结构中?
▷