题目重点:同 key 节点递归合并,不同 key 保留;先明确重复兄弟、值覆盖与输出顺序,再讨论 in-place 和版本一致性。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练讨论假设同一父节点下 key 唯一、节点值冲突按明确 merge policy 处理、输出按左树原子节点顺序再追加右树新 key;这些题目都没完整规定,写代码前必须让面试官确认。
- ‘in-place’可指修改左树节点而非创建整棵新树;但右树未匹配分支能否直接挂到左树、是否允许两个根之后共享可变节点,需核实。
解题路线
- 先核对两根 key 不同如何处理:返回虚拟根、并列森林、或拒绝。根 key 相同时递归合并。
- 在每个相配父节点处,建左孩子 key→node 索引;遍历右孩子,若 key 匹配则按 policy 合并值并递归合并孩子,否则按输出所有权规则追加或深拷贝。子树只在对应父节点的同 key 孩子之间合并,不能跨父节点全局按 key 合并。
- 若兄弟 key 可重复,单一 hash map 会覆盖数据,需要明确是按位置配对、合并所有同 key、还是保留多个;顺序语义也决定最终输出。
- in-place 合并期间如果别的线程读取左树,可能看到一半更新。粗粒度树锁最简单;读多写少可 copy-on-write 整棵/路径,完成后 CAS 版本指针发布,读者持稳定快照。按节点细锁要固定锁顺序防死锁,且跨节点一致性仍需处理。
- 若左右树可能共享节点或出现环,就不是普通树 DFS;需记录访问身份或先验证结构,避免无限递归和重复修改。
手动走一遍
左根 R 孩子 A(x=1)、B;右根 R 孩子 A(x=2)、C。按左值覆盖策略(仅训练假设)合并后孩子 A 合并其子树并保留 x=1,B 保留,C 追加;若右值覆盖则 A.x=2。未指定策略时这两种都不能称原题答案。
规模与取舍
总节点 N,若每层为左孩子建 key map,并遍历右孩子一次,平均 O(N) 时间、O(当前合并层孩子数+递归深度) 额外空间;深度 D 可能达 N,需考虑迭代。复制未匹配分支会额外占其节点数。并发锁/拷贝成本另计。
易错点与追问
容易失分的边界
- 只要 key 相同就跨不同父节点合并,破坏树结构。
- 默认覆盖哪棵树的 value 而不问。
- 重复兄弟 key 被 map 悄悄覆盖。
- 把右树子节点直接挂到左树却仍让右树可变共享。
- 并发读看见半成品树,却声称线程安全。
继续深挖
- 根 key 不同返回什么?
- 重复兄弟 key 怎样匹配?
- value 采用左/右/合并策略?
- 在高读低写下如何发布一致版本?
