题目
你有两颗非常大的二叉树:T1,有几百万个节点;T2有几百个节点。
设计一个算法,判断T2是否为T1的子树。
如果T1有一个节点n,其子树与T2一模一样,则T2为T1的子树。也就是说,从节点n
处把树砍断,得到的树与T2完全相同。
设计一个算法,判断T2是否为T1的子树。
如果T1有一个节点n,其子树与T2一模一样,则T2为T1的子树。也就是说,从节点n
处把树砍断,得到的树与T2完全相同。
分析
方法一:在规模较小且较简单的问题中,我们可以创建一个字符串,表示中序和前序遍历结果。若T2的前序遍历是T1前序遍历的子串,并且T2中序遍历是T1中序遍历的子串,则T2是T1的子树。
利用后缀树可以在线性时间内检查是否为子串,因此就最差情况的时间复杂度而言,这个算法是相当高效的。但是就本题而言,数据量过大,空间开销过大。
方法二:搜索较大的树T1,每当T1的某个节点与T2的根节点相同时,就调用matchTree方法判断T1子树与T2是否完全匹配;
代码
/*
题目:你有两颗非常大的二叉树:T1,有几百万个节点;T2有几百个节点。
设计一个算法,判断T2是否为T1的子树。
如果T1有一个节点n,其子树与T2一模一样,则T2为T1的子树。也就是说,从节点n
处把树砍断,得到的树与T2完全相同。
*/
#include <iostream>
#include <cstdlib>
#include <vector>
#include <queue>
using namespace std;
/*二叉树节点数据结构*/
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
const int flag = INT_MAX;
TreeNode *generateTree(vector<int> &nums)
{
if (nums.empty())
return NULL;
TreeNode *root = new TreeNode(nums[0]);
queue<TreeNode *> que;
que.push(root);
//求出所给元素个数,对应二叉查找树节点个数
int size = nums.size();
for (int i = 1; i < size; i += 2)
{
//处理队首节点的左右子树
TreeNode *tmp = que.front();
TreeNode *left = NULL, *right = NULL;
//定义非空左子树
if (nums[i] != flag)
{
left = new TreeNode(nums[i]);
que.push(left);
}
//定义非空右子树
if (i + 1 < size && nums[i + 1] != flag)
{
right = new TreeNode(nums[i + 1]);
que.push(right);
}
tmp->left = left;
tmp->right = right;
//弹出当前处理的节点
que.pop();
}
return root;
}
class Solution {
public:
bool containsTree(TreeNode *t1, TreeNode *t2)
{
if (t2 == NULL)
return true;
return subTree(t1, t2);
}
/*判断t2是否为t1的子树*/
bool subTree(TreeNode *t1, TreeNode *t2)
{
if (t1 == NULL)
return false;
if (t1->val == t2->val)
return matchTree(t1, t2);
else
return subTree(t1->left, t2) || subTree(t1->right, t2);
}
/*判断两颗树是否完全一致*/
bool matchTree(TreeNode *t1, TreeNode *t2)
{
if (t1 == NULL && t2 == NULL)
return true;
else if (t1 == NULL || t2 == NULL)
return false;
else if (t1->val != t2->val)
return false;
else
return matchTree(t1->left, t2->left) && matchTree(t1->right, t2->right);
}
};
int main()
{
vector<int> v1 = { 7, 6, flag, 4, flag, 2, 5, 8, 3, flag, flag, flag, flag, flag, flag };
TreeNode *t1 = generateTree(v1);
vector<int> v2 = {2, 8, 3};
TreeNode *t2 = generateTree(v2);
cout << Solution().containsTree(t1, t2) << endl;
system("pause");
return 0;
}