题目链接:572. 另一棵树的子树
题目:
给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。
二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。
示例 1:
输入:root = [3,4,5,1,2], subRoot = [4,1,2]
输出:true
示例 2:
输入:root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
输出:false
提示:
- root 树上的节点数量范围是 [1, 2000]
- subRoot 树上的节点数量范围是 [1, 1000]
- -104 <= root.val <= 104
- -104 <= subRoot.val <= 104
思路和算法:
采用双层深度优先遍历,外层和内层:
1、外层深度优先遍历:前序遍历在root树找到与subRoot树根节点值相同的节点;
2、内层深度优先遍历:遍历当前节点的左右子树。
对于外层深度优先遍历:
(1)确定递归的参数和返回值:参数:root树的节点和subRoot树的根节点,返回值:布尔类型。
bool isSubtree(TreeNode* root, TreeNode* subRoot) {}
(2)确定终止条件:如果root树节点为空,则root节点和subRoot节点值不相等,即没找到与subRoot节点值相等的root节点。
if (!root) return false;
(3)确定单层递归逻辑:从root节点开始查找和subRoot结构和节点值相同的节点以及递归当前节点的左右子树,任意一种情况存在,则返回真表示存在subRoot。
return compare(root, subRoot) || isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
单层递归逻辑也可等效于:
bool res0 = compare(root, subRoot); //中
bool res1 = isSubtree(root->left, subRoot); //左
bool res2 = isSubtree(root->right, subRoot); //右
return res0 || res1 || res2;
对于内层深度优先遍历:
(1)确定递归的参数和返回值:参数:两棵树的节点,返回值:布尔类型。
bool compare(TreeNode* root, TreeNode* subRoot) {}
(2)确定终止条件:如果两棵树的节点都为空,则两树具有相同结构和节点值,返回真;如果两棵树任意一个节点为空,则两树结构不同,返回假;如果两棵树对应节点的值不等,则两树节点值不同,返回假。剩下的情况就是结构和节点值相同的情况。
//如果两棵树的节点都为空,则两树具有相同结构和节点值
if (!root && !subRoot) return true;
//两棵树任意一个节点为空,则两树结构不同
else if (!root || !subRoot) return false;
//两棵树对应节点的值不等,则两树节点值不同
else if (root->val != subRoot->val) return false;
(3)确定单层递归逻辑:递归两棵树的左右子树,比较结构和节点值。
return compare(root->left, subRoot->left) && compare(root->right, subRoot->right);
代码(c++):
/**
* 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:
/* 外层深度优先遍历:前序遍历在root树找到与subRoot树根节点值相同的节点*/
//确定递归的参数和返回值
//参数:root树的节点和subRoot树的根节点,返回值:布尔类型
bool isSubtree(TreeNode* root, TreeNode* subRoot) {
//确定终止条件
//如果root树节点为空
if (!root) return false;
//确定单层递归逻辑
//compare(root, subRoot); //中
//isSubtree(root->left, subRoot); //左
//isSubtree(root->right, subRoot); //右
return compare(root, subRoot) || isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}
private:
/* 内层深度优先遍历:遍历当前节点的左右子树*/
//确定递归的参数和返回值
//参数:两棵树的节点,返回值:布尔类型
bool compare(TreeNode* root, TreeNode* subRoot) {
//确定终止条件
//如果两棵树的节点都为空,则两树具有相同结构和节点值
if (!root && !subRoot) return true;
//两棵树任意一个节点为空,则两树结构不同
else if (!root || !subRoot) return false;
//两棵树对应节点的值不等,则两树节点值不同
else if (root->val != subRoot->val) return false;
//确定单层逻辑
//递归两棵树的左右子树,比较结构和节点值
else return compare(root->left, subRoot->left) && compare(root->right, subRoot->right);
}
};