1.题目描述
检查子树。你有两棵非常大的二叉树:T1,有几万个节点;T2,有几万个节点。设计一个算法,判断 T2 是否为 T1 的子树。
如果 T1 有这么一个节点 n,其子树与 T2 一模一样,则 T2 为 T1 的子树,也就是说,从节点 n 处把树砍断,得到的树与 T2 完全相同。
注意: 此题相对书上原题略有改动。
示例 1:
输入:t1 = [1, 2, 3], t2 = [2]
输出:true
示例 2:
输入:t1 = [1, null, 2, 4], t2 = [3, 2]
输出:false
提示:
- 树的节点数目范围为
[0, 20000]。
2.解题思路(核心:拆分为 “找候选节点 + 匹配子树” 两步)
二叉树问题的核心是递归拆解,把复杂问题拆成两个简单子问题:
- 找候选节点:遍历
t1的所有节点,找到和t2根节点值相同的节点(只有值相同,才有可能是匹配的起点); - 验证匹配:对每个候选节点,检查以该节点为根的子树是否和
t2完全一致(结构 + 值都匹配)。
具体步骤(带边界条件)
-
边界条件(递归终止) :
- 如果
t2为空:直接返回true(空树是任何树的子树); - 如果
t1为空但t2非空:返回false(空树不可能包含非空子树);
- 如果
-
核心逻辑:
- 第一步:检查当前
t1节点是否能和t2完全匹配(调用isSameTree辅助函数); - 第二步:如果当前节点不匹配,递归检查
t1的左子树是否包含t2,或t1的右子树是否包含t2;
- 第一步:检查当前
-
辅助函数
isSameTree:专门检查两个树是否 “完全相同”(结构 + 值):- 两个树都为空 →
true; - 一个空、一个非空 →
false; - 节点值不同 →
false; - 递归检查左子树和右子树都相同 →
true。
- 两个树都为空 →
3.代码实现
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool checkSubTree(TreeNode* t1, TreeNode* t2) {
if(t2 == nullptr){
return true;
}
if(t1 == nullptr){
return false;
}
return isSameTree(t1,t2) || checkSubTree(t1->left,t2) || checkSubTree(t1->right,t2);
}
//检查两个树是否完全相同(结构+值)
bool isSameTree(TreeNode* t1,TreeNode* t2){
if(t1 == nullptr && t2 == nullptr){
return true;
}
if(t1 == nullptr|| t2 ==nullptr){
return false;
}
if(t1->val != t2->val){
return false;
}
return isSameTree(t1->left,t2->left) && isSameTree(t1->right,t2->right);
}
};