572. 另一棵树的子树
题目
给你两棵二叉树 root
和 subRoot
。检验 root
中是否包含和 subRoot
具有相同结构和节点值的子树。如果存在,返回 true
;否则,返回 false
。
二叉树 tree
的一棵子树包括 tree
的某个节点和这个节点的所有后代节点。tree
也可以看做它自身的一棵子树。
解题思路
该问题可以分解成两个子问题:
- 如何判断两棵树是否相同?
- 如何在主树中寻找可能的子树?
判断两棵树是否相同(isSameTree)
两棵树相同的条件是:
- 根节点值相同
- 左子树相同
- 右子树相同
递归终止条件:
- 如果两个节点都为空,返回 true
- 如果一个为空另一个不为空,返回 false
- 如果两个节点的值不同,返回 false
寻找子树(isSubtree)
我们需要从主树的每个节点出发,判断以该节点为根的子树是否与目标子树相同:
- 如果当前节点为空,返回 false(空树不可能包含非空子树)
- 检查当前节点为根的树是否与目标子树相同
- 如果不同,递归检查左子树和右子树
解题
- 提前判断特殊情况:
- 如果 subRoot 为空,根据定义,空树是任何树的子树,返回 true
- 如果 root 为空但 subRoot 不为空,显然返回 false
- 递归的顺序:
- 先判断当前树是否与子树相同
- 再递归检查左右子树
代码
/*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/
bool isSameTree(struct TreeNode* p, struct TreeNode* q) {// 如果两个节点都为NULL,认为相同if (p == NULL && q == NULL) return true;// 如果一个为NULL,一个不为NULL,认为不同if (p == NULL || q == NULL) return false;// 如果值不同,认为不同if (p->val != q->val) return false;// 递归比较左右子树return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot) {// 如果子树为空,根据定义,空树是任何树的子树if(subRoot == NULL){return true;}// 如果主树为空但子树不为空,返回falseif(root == NULL){return false;}// 检查当前树是否与子树相同if(!isSameTree(root, subRoot)){// 递归判断左右子树和subRoot是否相同return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);} else{return true;}
}