剑指offer17_树的子结构_题解
树的子结构
题目描述
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
示例1
输入
{8,8,#,9,#,2,#,5},{8,9,#,2}
返回值
true
分析
方案一:递归
dfs(A, B)函数
- 终止条件:
- 当树 \(B\) 为空:说明 \(B\) 已匹配完成,因此返回 \(true\)
- 当树 \(A\) 为空,树 \(B\) 不为空:说明已经越过 \(A\) 的叶子节点,返回 \(false\)
- 当节点 \(A\) 和 \(B\) 的值不同:说明匹配失败,返回 \(false\)
- 返回值:
- 判断 \(A\) 和 \(B\) 的左子节点是否相等,即 \(dfs(A->left, B->left)\)
- 判断 \(A\) 和 \(B\) 的左子节点是否相等,即 \(dfs(A->right, B->right)\)
HasSubtree(A, B)函数
- 特例处理:当树 \(A\) 为空或树 \(B\) 为空时,直接返回 \(false\)
- 返回值:若树 \(B\) 是树 \(A\) 的子结构,则满足以下三种情况之一
- 以节点 \(A\) 为根节点的子树包含树 \(B\)
- 树 \(B\) 是树 \(A\) 左子树的子结构
- 树 \(B\) 是树 \(A\) 右子树的子结构
/**
时间复杂度:O(n)
空间复杂度:O(1)
**/
class Solution
{
public:
bool dfs(TreeNode *r1, TreeNode *r2)
{
// 如果树B为空,说明B已匹配完成,因此返回true
if (!r2)
return true;
// 如果树B不为空,但是树A为空,说明已经越过A的叶子节点,返回false
if (!r1)
return false;
// 如果树A的根节点和树B的根节点值不相等,直接返回false
// 否则相等,继续判断A的左子树和B的右子树
return r1->val == r2->val && dfs(r1->left, r2->left) && dfs(r1->right, r2->right);
}
bool HasSubtree(TreeNode *pRoot1, TreeNode *pRoot2)
{
// 特判树为空的情况
if (!pRoot1 || !pRoot2)
return false;
// 1.以节点A为根节点的子树包含树B
// 2.树B是树A左子树的子结构
// 3.树B是树A右子树的子结构
return dfs(pRoot1, pRoot2) || HasSubtree(pRoot1->left, pRoot2) || HasSubtree(pRoot1->right, pRoot2);
}
};