P1185. 绘制二叉树
考点
- 二叉树
- 模拟
题解
1 |
|
思路
具体实现细节见代码,主要阐述一下编程思维
很容易想到实现流程:
最终要输出结果,所以需要二维数组
ans
来保存还要一个标志数组
del
记录第几层的第几个结点需要被删除从根结点开始,递归地处理左子树与右子树
左右子树的处理次序与答案不相关,DFS或BFS的实现也与答案不相关;因为本身其实是一颗满二叉树
但这种按层次处理的二叉树问题,显然用BFS能极大降低思维难度
若用BFS实现
每次当前的父结点判断左右孩子是否需要被删除:
需要被删除的就不填充斜杠与孩子结点
保留的孩子则填充与父结点之间的斜杠;若孩子所处不在最后一层,就将其添加进队列进行下一轮扩展
(最后一层是叶子结点,没有孩子,扩展啥)
答案的存储样式如下:

先找找x轴,即二叉树的高度height
的规律
m | height |
---|---|
1 | 1 |
2 | 3 |
3 | 6 |
4 | 12 |
得到\(height=3\times
2^{m-2}\)这一规律,其中m = 1
只有根结点的时候特判即可
接下来找y轴,二叉树的宽度width
的规律
m | width |
---|---|
1 | 1 |
2 | 5 |
3 | 11 |
4 | 23 |
得到\(width=6\times
2^{m-2}-1\)这一规律,同样m = 1
时特判
根结点的位置规律:\(\text{横坐标}x=height-1\),\(\text{纵坐标}y=\frac{width-1}{2}\)
由于满二叉树的对称性,尽管题目没有给出其他层数的数据,但知道根结点就能在草稿纸上推斜杠的规律
正常情况下根结点所在层次定义为第一层,但是斜杠的规律就不好找;所以定义叶子结点为固定的第一层
设当前层次为lv
,斜杠数定义为当前层次的父结点与其左或右孩子中间的斜杠数
比如lv = 3
,此时斜杠数等于第3层的父结点与第2层的左或右孩子中间的斜杠数
lv | 斜杠数 |
---|---|
1 | 0 |
2 | 1 |
3 | 2 |
4 | 5 |
5 | 11 |
6 | 23 |
得到\(\text{斜杠数}=3\times
2^{lv-3}-1\),lv
等于2时特判
这是叶子结点为第一层时的定义,需要将其转换为根结点为第一层的定义:\(\text{斜杠数}=3\times 2^{m+1-lv-3}-1\)
你可以自己发现一下规律,有数组
{1, 2, 3, 4}
要变成
{4, 3, 2, 1}
要如何做呢?每个元素被5减不就好了嘛~
如何断定当前结点是该层的第几个呢?
假设根结点的下标为1,以顺序存储的办法
那么左孩子的下标为父结点下标 * 2
,右孩子的下标为父结点下标 * 2 + 1

假设当前为k + 1
层,下标为id
;根据满二叉树的性质,本层之前共有\(2^k-1\)个结点
那么该节点在本层的次序,不就等于\(id-\left( 2^k-1 \right)\)嘛