题目
树的子结构。输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
B是A的子结构, 即 A中有出现和B相同的结构和节点值。
例如:
给定的树 A:
3
/ \
4 5
/ \
1 2
给定的树 B:
4
/
1
返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点值。
法一:递归
- 先在A树中找到和B树根节点相同的节点
- 找到相同的根节点后,从根节点开始判断A是否包含B树
- 当B为空,说明B已匹配完成,返回true
- 当A为空,说明已经超过A叶子节点,即匹配失败,返回false
- 当节点A和B的值不同,说明匹配失败,返回false
时间复杂度 O(MN)
M:A树的节点数量
N:B树的节点数量
空间复杂度:O(M)
A和B都退化成链表时,递归调用深度最大
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <list>
using namespace std;
struct TreeNode
{
int data;
TreeNode * left;
TreeNode * right;
TreeNode(int value)
{
data = value;
left = NULL;
right = NULL;
}
};
/*
二叉树的子结构
1:先在A树中找到和B树根节点相同的节点
2:判断A是否包含B树
2.1:当B为空,说明B已匹配完成,返回true
2.2: 当A为空,说明已经超过A叶子节点,即匹配失败,返回false
2.3: 当节点A和B的值不同,说明匹配失败,返回false
时间复杂度 O(MN)
M:A树的节点数量
N:B树的节点数量
空间复杂度:O(M)
A和B都退化成链表时,递归调用深度最大
*/
// 判断A树是否包含B树
bool Judge(TreeNode * A , TreeNode * B)
{
if(B == NULL) //2.1:当B为空,说明B已匹配完成,返回true
{
return true;
}
if(A == NULL) //2.2: 当A为空,说明已经超过A叶子节点,即匹配失败,返回false
{
return false;
}
if(A->data == B->data) //2.3: 当节点A和B的值不同,说明匹配失败,返回false
{
return Judge(A->left , B->left) && Judge(A->right , B->right);
}
}
bool IsSubTree(TreeNode * A , TreeNode * B)
{
if(A == NULL || B == NULL)
{
return false;
}
// 判断A当前节点为根节点的是否包含B子树
if(Judge(A , B))
{
return true;
}
else
{
return IsSubTree(A->left , B) || IsSubTree(A->right , B);
}
}
int main()
{
TreeNode root(8);
TreeNode node1(4);
TreeNode node2(2);
TreeNode node3(9);
TreeNode node4(12);
TreeNode node5(1);
TreeNode node6(5);
root.left = &node1;
root.right = &node2;
node1.left = &node3;
node1.right = &node4;
node2.left = &node5;
node2.right = &node6;
TreeNode subnode(4);
TreeNode subnode_1(9);
TreeNode subnode_2(12);
subnode.left = &subnode_1;
subnode.right = &subnode_2;
cout << IsSubTree(&root , &subnode) << endl;
return 0;
}