BM41 输出二叉树的右视图¶
中等通过率 54.01%python3核心代码模式样例通过牛客 AC树
讲解章节:树的基础与遍历
一句话
先按前序+中序重建树,再层序遍历取每层最后一个节点。
解题思路¶
这题考什么¶
签名收的不是树而是两个数组,所以它是两道题接在一起: 先做一遍 BM40「重建二叉树」,再在还原出的树上求右视图。
第一步 · 重建。前序首元素是根,它在中序里的下标把中序切成左右两段, 左段长度同时也切开了前序,对两段重复即可。用「值 -> 中序下标」的哈希表 把每层找根从 O(n) 降到 O(1),整体 O(n);用显式栈存「节点 + 前序区间 + 中序区间」做成迭代。
第二步 · 右视图。所谓右视图是「站在树的右边往左看,每层只看得见最右 那一个节点」——注意是每层的最右节点,不是「从根一路往右走」:
[1,2,4,5,3] / [4,2,5,1,3] 重建后
1 第 1 层最右: 1
/ |
2 3 第 2 层最右: 3
/ |
4 5 第 3 层最右: 5 -> [1, 3, 5]
节点 3 没有孩子,第 3 层能看见的是左子树里的 5。一路往右走会在 3 处
停下,只得到 [1, 3],与样例的 [1,3,5] 不符。
所以按层做 BFS,每层取最后一个节点的值。这里用「整层推进」的写法: cur 里恰好是完整的一层,取 cur[-1].val,再把这一层的非空孩子按先左后右 收集成下一层——顺序始终保持从左到右,末位自然就是最右节点。
数据规模与复杂度¶
0 <= n <= 10000,节点值在 [1, 10000] 且互不相同;时限「其他语言 2 秒」。 重建 O(n) + 层序 O(n),时间 O(n);空间 O(n):下标字典、重建栈、层数组 各 O(n)。
坑在哪¶
- 右视图不等于「一路向右」。上面 [1,2,4,5,3] 的例子就是反例: 右子树到第 2 层就断了,第 3 层露出来的是左子树的节点。 只有按层扫才能保证每层都取到那个真正最右的节点。
- 收集下一层必须保持「先左后右」。顺序一旦颠倒,cur[-1] 取到的就成了 每层的最左节点,等于求左视图。
- 哈希表定位根不是可选优化。n 到 1e4,每层在中序里线性扫找根, 链状树上是 1e8 次比较,Python 在 2 秒时限内跑不完(判题机还比本机慢 数倍,本地耗时要按 3~4 倍留余量)。
- 递归重建同样不行:n 到 1e4,链状树的递归深度就是 1e4,远超 CPython 默认的 1000 层上限,会 RecursionError;见 DFS 深度优先搜索 的 60.4 节。
- n 可以为 0,空数组返回 []。两道守卫缺一不可:_build 里挡住 preOrder[0] 的 IndexError,solve 里挡住对 None 取 .val。
- 判题只调 solve,_build 是自己拆出来的辅助方法。签名约束只作用于 模板给定的那个方法,辅助方法叫什么、放在哪都不影响判题。
参考实现¶
[:octicons-arrow-left-16: BM40](BM40.md) [BM42 :octicons-arrow-right-16:](BM42.md)