← 返回编程题库
coding-binary-tree-invert-mirror简单免费版2000ms未尝试

翻转二叉树(镜像)

Invert Binary Tree (Mirror)

开始编码

给一棵嵌套字典表示的二叉树,每个节点形如 {"value": v, "left": L, "right": R},其中 LR 自身也是树(或 None 表示「没有孩子」)。请返回翻转后的(镜像)树:在每个节点上交换它的左右子树。这就是经典的 LeetCode 226。输出必须是一棵全新的、结构已交换好的树;节点 value 原样保留。

递归解只有三行:tree is None 时返回 None,否则递归两个孩子拿到翻转后的两个子树,再返回一个 leftright 已交换的新节点。镜像是个结构性变换——它从不读也从不改任何节点的 value,只调整父子之间的连线。时间复杂度 O(n_nodes)(每个节点恰好访问一次),空间 O(tree_height) 用于递归栈。

Examples

solution({"value": 4, "left": {"value": 2, "left": {"value": 1, ...}, "right": {"value": 3, ...}}, "right": {"value": 7, "left": {"value": 6, ...}, "right": {"value": 9, ...}}}) 返回 {"value": 4, "left": {"value": 7, "left": {"value": 9, ...}, "right": {"value": 6, ...}}, "right": {"value": 2, "left": {"value": 3, ...}, "right": {"value": 1, ...}}}。根 4 不动。原本的左子树(根 2、叶子 1 和 3)和右子树(根 7、叶子 6 和 9)整体互换位置,每个子树内部的两个叶子也互换。这是 LeetCode 226 的原题示例。

solution({"value": 7, "left": null, "right": null}) 返回 {"value": 7, "left": null, "right": null}。单叶节点没有孩子可以交换,交换两个 None 还是两个 None,输出结构上和输入完全相同。

solution(None) 返回 None。空树是递归基底。如果不写这一支,第一次访问 tree["left"] 就会立刻抛 TypeError: 'NoneType' is not subscriptable

签名见 stubs/stub.py

Practical context

树的镜像操作出现在任何需要把递归结构「翻转方向」的场景里。在格子树期权定价(二叉/三叉模型)中,把资产价格树关于初始节点做反射,相当于把每一步的「上涨」和「下跌」互换——得到的镜像树会用「时间反演」动力学给同一份期权定价,这是在 Cox–Ross–Rubinstein 格子上做反向归纳健壮性检查、以及验证看涨–看跌对称性的核心套路。在决策树概率题里,把场景树镜像一下就等价于把每个二元结果的标签互换(正面 ↔ 反面、成功 ↔ 失败),这是「把贝叶斯后验树看成对偶事件标签下的版本」最干净的写法——比较一棵后验树和它「补事件」孪生树时非常好用。在强化学习里的对称两人零和博弈树(如国际象棋局面评估、交替走子的 Minimax)中,镜像操作把「白方视角下的局面」映成「黑方视角下的同一局面」,于是单一一份学到的价值函数可以在两个玩家视角间复用。这个模式还出现在表达式树代数恒等变换(在每个交换运算符上交换左右操作数实现交换律重写)以及双向图算法(把树状有向图镜像就是把所有边反向)里。能解 LeetCode 226 的那三行递归,就是上面所有这些场景背后的同一台引擎。

约束条件

  • 0 ≤ 树大小 ≤ 10^4 个节点
  • 树深度 ≤ 1000
  • 每个节点是字典 {value, left, right};left/right 自身也是树或 null
  • 节点值可以是任意可哈希类型(int、float、str 等)
  • 空树用 None / null 表示

样例

Case 1 · empty tree returns empty

输入: [null]

期望: null

空树(None)翻转后还是空树。这是递归基底:函数第一行必须先判 `tree is None`,否则后面访问 `tree["left"]` 会立刻报 KeyError/TypeError。

Case 2 · single node unchanged

输入: [{"value":7,"left":null,"right":null}]

期望: {"value":7,"left":null,"right":null}

单节点没有左右子树(都是 None),交换两个 None 还是两个 None,节点值保持不变。这道题钉死「叶子翻转后等于自己」的约定。

Case 3 · LeetCode 226 canonical example

输入: [{"value":4,"left":{"value":2,"left":{"value":1,"left":null,"right":null},"right":{"value":3,"left":null,"right":null}},"right":{"value":7,"left":{"value":6,"left":null,"right":null},"right":{"value":9,"left":null,"right":null}}}]

期望: {"value":4,"left":{"value":7,"left":{"value":9,"left":null,"right":null},"right":{"value":6,"left":null,"right":null}},"right":{"value":2,"left":{"value":3,"left":null,"right":null},"right":{"value":1,"left":null,"right":null}}}

LeetCode 226 原题示例:原树根 4,左子树 [2,1,3]、右子树 [7,6,9]。翻转后根仍为 4,但左右子树整体互换,并且每个子树内部也镜像了——左变 [7,9,6]、右变 [2,3,1]。每一层都做了交换。

最近提交

还没有提交记录。

编码区

实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。

加载编辑器...
计时0:00

默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。

Case 1 · empty tree returns empty

输入: [null]

期望: null

空树(None)翻转后还是空树。这是递归基底:函数第一行必须先判 `tree is None`,否则后面访问 `tree["left"]` 会立刻报 KeyError/TypeError。

Case 2 · single node unchanged

输入: [{"value":7,"left":null,"right":null}]

期望: {"value":7,"left":null,"right":null}

单节点没有左右子树(都是 None),交换两个 None 还是两个 None,节点值保持不变。这道题钉死「叶子翻转后等于自己」的约定。

Case 3 · LeetCode 226 canonical example

输入: [{"value":4,"left":{"value":2,"left":{"value":1,"left":null,"right":null},"right":{"value":3,"left":null,"right":null}},"right":{"value":7,"left":{"value":6,"left":null,"right":null},"right":{"value":9,"left":null,"right":null}}}]

期望: {"value":4,"left":{"value":7,"left":{"value":9,"left":null,"right":null},"right":{"value":6,"left":null,"right":null}},"right":{"value":2,"left":{"value":3,"left":null,"right":null},"right":{"value":1,"left":null,"right":null}}}

LeetCode 226 原题示例:原树根 4,左子树 [2,1,3]、右子树 [7,6,9]。翻转后根仍为 4,但左右子树整体互换,并且每个子树内部也镜像了——左变 [7,9,6]、右变 [2,3,1]。每一层都做了交换。