LeetCode.面试题04.10.[检查子树]

3 阅读2分钟

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

提示:

  1. 树的节点数目范围为 [0, 20000]

2.解题思路(核心:拆分为 “找候选节点 + 匹配子树” 两步)

二叉树问题的核心是递归拆解,把复杂问题拆成两个简单子问题:

  1. 找候选节点:遍历 t1 的所有节点,找到和 t2 根节点值相同的节点(只有值相同,才有可能是匹配的起点);
  2. 验证匹配:对每个候选节点,检查以该节点为根的子树是否和 t2 完全一致(结构 + 值都匹配)。

具体步骤(带边界条件)

  1. 边界条件(递归终止)

    • 如果 t2 为空:直接返回 true(空树是任何树的子树);
    • 如果 t1 为空但 t2 非空:返回 false(空树不可能包含非空子树);
  2. 核心逻辑

    • 第一步:检查当前 t1 节点是否能和 t2 完全匹配(调用 isSameTree 辅助函数);
    • 第二步:如果当前节点不匹配,递归检查 t1 的左子树是否包含 t2 t1 的右子树是否包含 t2
  3. 辅助函数 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);
    }
};