对称二叉树判定
Symmetric Binary Tree Check
开始编码给一棵二叉树的根节点(空树时为 None)。每个节点是 dict {"value": v, "left": ..., "right": ...},其中 left 和 right 要么是另一个节点 dict,要么是 None。当树绕根节点镜像对称时返回 True——也就是左子树是右子树的镜像,递归成立。空树和单节点树都视为对称。
请实现 solution(tree: dict | None) -> bool。标准做法是双参数递归谓词 is_mirror(a, b),按镜像关系直接定义:两棵子树互为镜像当且仅当根的值相等、且一棵的左子树镜像另一棵的右子树、且一棵的右子树镜像另一棵的左子树。具体写:is_mirror(a, b) = (a is None and b is None) or (a is not None and b is not None and a['value'] == b['value'] and is_mirror(a['left'], b['right']) and is_mirror(a['right'], b['left']))。从原始根节点出发,返回 is_mirror(tree['left'], tree['right'])(tree is None 时直接当 True 处理)。
Examples
solution({"value": 1, "left": {"value": 2, "left": {"value": 3, ...}, "right": {"value": 4, ...}}, "right": {"value": 2, "left": {"value": 4, ...}, "right": {"value": 3, ...}}}) 返回 True。这是 LeetCode 101 经典对称例子 [1,2,2,3,4,4,3]:根 1,两个孩子都是 2;左子树叶子 (3, 4),右子树叶子 (4, 3)——刚好是镜像配对。
solution({"value": 1, "left": {"value": 2, "left": null, "right": {"value": 3, ...}}, "right": {"value": 2, "left": null, "right": {"value": 3, ...}}}) 返回 False。LeetCode 101 经典非对称例子 [1,2,2,null,3,null,3]:两边子树都是「只有右孩子值为 3」,不交叉的递推会错误返回 True,但结构镜像要求 left.right 对 right.left = None,遇到缺失节点立即失败。
solution({"value": 1, "left": {"value": 2, ...}, "right": {"value": 3, ...}}) 返回 False。两个孩子在最顶层值不同,不论下方结构如何,值检查立刻失败。
签名见 stubs/stub.py。
Practical context
镜像对称检查频繁出现在涉及树形校验的金融流水线里——并且常常出现在你想不到的地方。期权定价里的重组二叉树(CRR、Jarrow-Rudd、Leisen-Reimer)按构造在「上/下步结构上」就是镜像对称的:每个节点的「先上后下」孩子等于「先下后上」孩子,正是这个性质把指数级分支压缩成 O(n²) 的格点。定价引擎的单测在树构造完之后会反复校验这个不变量,因为构造器的 bug(比如对乘性过程错把 u * d 写成 u + d、或者忘了合并合流节点)可能给你一棵在玩具输入上能正确定价、但在大时间维度上吃内存且精度泄漏的非重组树。同样的模式也出现在随机规划的场景树生成器(上下分支必须在概率质量上镜像才能保持风险中性)、清算所账本的 CRT/Merkle 树平衡检查、以及——最常见的——手写定价 DSL 的表达式树校验里,那种地方解析错误经常表现为一棵左偏 AST,对称性检查会在下游代码尝试求值之前就把它拒掉。双参数递归谓词是任何「结构性比较两棵树」任务的经典模板;这里把交叉对 (a.left, b.right) / (a.right, b.left) 内化之后,其它变种——同一性比较、子树包含、同构判定——都只要改一行就能写出来。
约束条件
- 0 ≤ 树的节点数 ≤ 10^4
- 树的深度 ≤ 1000
- 每个节点是 dict {value, left, right};left 和 right 要么是另一个节点,要么是 null
- 空树(null)视为对称
- 节点值可以是任意可比较类型(int、str 等),不必唯一
样例
Case 1 · null tree is symmetric
输入: [null]
期望: true
空树(None)按惯例视为对称——没有节点可以违反镜像约束。这是 `solution(None) -> True` 的递归基底,实现必须先判 `tree is None`,否则后面 `tree["left"]` 会立刻 KeyError/TypeError。
Case 2 · single node is symmetric
输入: [{"value":7,"left":null,"right":null}]
期望: true
单节点没有左右子树(都是 None),自然满足 `is_mirror(None, None) = True`。这道题钉死「叶子被视为对称」的约定,避免把 `is_mirror(None, None)` 错写成 False。
Case 3 · LeetCode 101 canonical symmetric example
输入: [{"value":1,"left":{"value":2,"left":{"value":3,"left":null,"right":null},"right":{"value":4,"left":null,"right":null}},"right":{"value":2,"left":{"value":4,"left":null,"right":null},"right":{"value":3,"left":null,"right":null}}}]
期望: true
LeetCode 101 原题中的对称例子 [1,2,2,3,4,4,3]:根 1 的左右孩子都是 2,左子树叶子是 (3,4) 而右子树叶子是 (4,3)——刚好镜像。验证 `is_mirror(left.left, right.right)` 和 `is_mirror(left.right, right.left)` 这两个交叉调用都被正确触发。
Case 4 · LeetCode 101 canonical asymmetric (value mismatch)
输入: [{"value":1,"left":{"value":2,"left":null,"right":{"value":3,"left":null,"right":null}},"right":{"value":2,"left":null,"right":{"value":3,"left":null,"right":null}}}]
期望: false
LeetCode 101 原题中的非对称例子 [1,2,2,null,3,null,3]:左右子树根都是 2,但左子树只有右孩子 3,右子树也只有右孩子 3——结构上**不**镜像(镜像要求左子树的右孩子对上右子树的左孩子)。`is_mirror(left.right=3, right.left=None)` 在结构对比时返回 False。一个常见的错误是把递归写成 `is_mirror(left.left, right.left) and is_mirror(left.right, right.right)`,那样会把这种树误判为对称。
最近提交
还没有提交记录。
编码区
实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
Case 1 · null tree is symmetric
输入: [null]
期望: true
空树(None)按惯例视为对称——没有节点可以违反镜像约束。这是 `solution(None) -> True` 的递归基底,实现必须先判 `tree is None`,否则后面 `tree["left"]` 会立刻 KeyError/TypeError。
Case 2 · single node is symmetric
输入: [{"value":7,"left":null,"right":null}]
期望: true
单节点没有左右子树(都是 None),自然满足 `is_mirror(None, None) = True`。这道题钉死「叶子被视为对称」的约定,避免把 `is_mirror(None, None)` 错写成 False。
Case 3 · LeetCode 101 canonical symmetric example
输入: [{"value":1,"left":{"value":2,"left":{"value":3,"left":null,"right":null},"right":{"value":4,"left":null,"right":null}},"right":{"value":2,"left":{"value":4,"left":null,"right":null},"right":{"value":3,"left":null,"right":null}}}]
期望: true
LeetCode 101 原题中的对称例子 [1,2,2,3,4,4,3]:根 1 的左右孩子都是 2,左子树叶子是 (3,4) 而右子树叶子是 (4,3)——刚好镜像。验证 `is_mirror(left.left, right.right)` 和 `is_mirror(left.right, right.left)` 这两个交叉调用都被正确触发。
Case 4 · LeetCode 101 canonical asymmetric (value mismatch)
输入: [{"value":1,"left":{"value":2,"left":null,"right":{"value":3,"left":null,"right":null}},"right":{"value":2,"left":null,"right":{"value":3,"left":null,"right":null}}}]
期望: false
LeetCode 101 原题中的非对称例子 [1,2,2,null,3,null,3]:左右子树根都是 2,但左子树只有右孩子 3,右子树也只有右孩子 3——结构上**不**镜像(镜像要求左子树的右孩子对上右子树的左孩子)。`is_mirror(left.right=3, right.left=None)` 在结构对比时返回 False。一个常见的错误是把递归写成 `is_mirror(left.left, right.left) and is_mirror(left.right, right.right)`,那样会把这种树误判为对称。