题目描述
给你一棵二叉树的根节点 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 = [11,12,13,null,14]
输出:
[[“”,””,””,”11″,””,””,””],
[“”,”12″,””,””,””,”13″,””],
[“”,””,”14″,””,””,””,””]]
解题思路
这道题主要是如何层序遍历二叉树,并且按照要求排列数字;
- 第一步,层序遍历,由于要考虑NULL情况,所以如果遇到NULL情况需要重新构造一个TreeNode;
- 第二步,根据深度,获取每层:int size = (int) Math.pow(2, res.size()) – 1;
- 第三步,构造按照题目要求构造结果。
如图:
将原来的树可以按照上述图示进行转换,这里我使用Integer.MIN_VALUE表示null;并且定义成 int none = Integer.MIN_VALUE;
第一步,使用BFS做层序遍历,最终遍历结果,[11], [12,13],[none,14,none,none];
第二步,计算每层的长度,上述总共3层,最后一层在每个元素中间需要使用空字符串填充,那么就是:元素数量 * 2 – 1;根据二叉树的性质:最后一层元素数量=(int) Math.pow(2, res.size()-1);最终换算成:(int) Math.pow(2, res.size()) – 1;
第三步,每一层需要填充空字符,参考下图:
如果是三层,效果如下:
如果是四层,效果如下:
最终效果如下:
总共4层:
第4层间隔:2的(4-4)次方 – 1 = 0
第3层间隔:2的(4-3)次方 – 1 = 1
第2层间隔:2的(4-2)次方 – 1 = 3
第1层间隔: 2的(4-1)次方 – 1 = 7
for (int i = 0; i < res.size(); i++) { List<String> l = new ArrayList<>(size); r.add(l); List<Integer> list = res.get(i); int v = (int) Math.pow(2, res.size()-i-1) - 1; for(int j=0;j<list.size();j++) { // before for(int m=0;m<v;m++) { l.add(""); } if(list.get(j) != none) { l.add(String.valueOf(list.get(j))); } else { l.add(""); } // after for(int m=0;m<v;m++) { l.add(""); } if(j != list.size()-1) { l.add(""); } } }
代码实现
import org.example.TreeNode;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
class Solution1 {
int none = Integer.MIN_VALUE;
public List<List<String>> printTree(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
Deque<TreeNode> deque = new LinkedList<>();
if (root != null) {
deque.offer(root);
}
int countNotNull = deque.size();
while (countNotNull != 0) {
int sz = deque.size();
List<Integer> list = new ArrayList<>();
countNotNull = 0;
for (int i = 0; i < sz; i++) {
TreeNode node = deque.poll();
list.add((node.val));
if (node.left != null) {
deque.offer(node.left);
countNotNull++;
} else {
deque.offer(new TreeNode(none));
}
if (node.right != null) {
deque.offer(node.right);
countNotNull++;
} else {
deque.offer(new TreeNode(none));
}
}
res.add(list);
}
List<List<String>> r = new ArrayList<>(res.size());
int size = (int) Math.pow(2, res.size()) - 1;
for (int i = 0; i < res.size(); i++) {
List<String> l = new ArrayList<>(size);
r.add(l);
List<Integer> list = res.get(i);
int v = (int) Math.pow(2, res.size()-i-1) - 1;
for(int j=0;j<list.size();j++) {
// before
for(int m=0;m<v;m++) {
l.add("");
}
if(list.get(j) != none) {
l.add(String.valueOf(list.get(j)));
} else {
l.add("");
}
// after
for(int m=0;m<v;m++) {
l.add("");
}
if(j != list.size()-1) {
l.add("");
}
}
}
return r;
}
public static void main(String[] args) {
Solution1 solution = new Solution1();
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.right = new TreeNode(4);
System.out.println(solution.printTree(root));
}
}
总结
这道题就是二叉树的层序遍历+完全二叉树的特点的题目,感觉更像一个数学题目,先找到规律,然后用代码完成数据展示。欢迎有更高效、更简洁的思路回复。