572. 另一棵树的子树(简单)
题目
给定两棵二叉树 root 与 subRoot,判断 root 中是否存在某个节点,使它以及它的全部后代所构成的树,与 subRoot 在结构和节点值上完全相同。存在返回 true,否则返回 false。
注意「子树」不是「部分重叠」:候选节点以下必须整棵一致,连空孩子的数量、位置都不能差。任意一棵树也可以看作它自身的子树。
自造示例一:
root: 1
/
2 3
/ /
4 5 6 7
subRoot: 2
/
4 5
输出:true自造示例二:
root: 1
/
2 3
/
4 5
subRoot: 2
/
4
输出:false例二中 root 里节点 2 有两个孩子 4,5,而 subRoot 的节点 2 只有一个左孩子 4;即使值能对上,结构不同也不能算。
约束:root 节点数 1 ≤ n ≤ 2000;subRoot 节点数 1 ≤ m ≤ 1000;节点值范围 -104 ≤ val ≤ 104。
思路
一句话:外层递归负责「在 root 里找候选根」,内层递归负责「判断从这个候选根开始是否与 subRoot 完全同构」。
最直白的想法是:既然子树可以从 root 的任意节点开始,就把每个节点都当作候选根,逐个拿去和 subRoot 比较。这个方向是对的;但只比较「当前节点值相等」是不够的,因为值相等不代表整棵子树相同,还必须一路比到左右孩子、比到叶子,空节点也要一一对应。
关键观察:二叉树是否相等,本身可以用递归精确描述——两棵树相等,当且仅当根值相等,且左子树相等、右子树相等。于是可以把问题拆成两个函数:一个负责「找起点」,一个负责「判相同」。
为什么这就够用?root 最多 2000 个候选起点,每次比较最多访问 subRoot 的 1000 个节点,最坏约 2 × 106 次访问,规模很小;而且一旦发现值不同或空位不同就立即返回,实际远快于上界,不需要更复杂的序列化技巧。
解法
递归流程如下:
- 若
subRoot为空,空树可视为任意树的子树,直接返回true(本题数据非空,这里是稳健处理)。 - 若
root为空而subRoot非空,说明这条路已经走到底仍没匹配,返回false。 - 先拿当前
root当候选根,调用same(root, subRoot);命中就返回true。 - 未命中则分别到左、右子树继续找,两边是短路或:
左边命中 || 右边命中。 same(p, q):两空为真;一空一非空为假;值不等为假;否则递归比较左右子树。
| 当前候选根 | same 比较 | 动作 |
|---|---|---|
| 节点 1 | 1 ≠ 2,立即失败 | 继续去左子树 |
| 节点 2 | 2=2,4=4,5=5,左右递归到底 | 命中,返回 true |
本篇为付费内容
您已阅读试读部分,购买后即可解锁全文。
⚠️ 本站内容已做唯一性标记并受版权保护,未经授权禁止转载,侵权必究。
还没有评论,来说两句?