对于两棵彼此独立的二叉树A和B,请编写一个高效算法,检查A中是否存在一棵子树与B树的拓扑结构完全相同。
给定两棵二叉树的头结点A和B,请返回一个bool值,代表A中是否存在一棵同构于B的子树。
这道题目表面上是一个二叉树题目,可以转换为字符串匹配的问题,首先将两个树转换为字符串,遍历这棵树注意在为空的地方加上#!这样可以保证树的唯一性,另外每一个节点后面要跟上#这样可以区分12和1 2这样的节点。之后利用KMP算法可以将字符串匹配的算法复杂度降到O(M+N)M和N是字符串的长度。
代码如下:
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class IdenticalTree {
public:
bool chkIdentical(TreeNode* A, TreeNode* B) {
string A_str{};
string B_str{};
treetostring(A,A_str);
treetostring(B,B_str);
return kmpjudge(A_str,B_str);
}
void treetostring(TreeNode* root,string &s)
{
if(root==NULL){
s+="#!";
return;
}
s+=to_string(root->val);
s+="#";
treetostring(root->left,s);
treetostring(root->right,s);
}
bool kmpjudge(string &A,string &B)
{
vector<int> next{};
calnext(B,next);
int i=0;
int j=0;
while(i!=A.size()&&j!=B.size())
{
if(A[i]==B[j])
{
++i;
++j;
}
else if(j==0)
++i;
else
j=next[j-1];
}
if(j==B.size())
return true;
return false;
}
void calnext(string &s,vector<int> &res)
{
vector<int> next(s.size(),0);
for(int i=1;i!=s.size();++i)
{
int j=i;
while(1)
{
if(s[next[j-1]]==s[i]){
next[i]=next[j-1]+1;
break;
}
else if(next[j-1]!=0)
j=next[j-1];
else
break;
}
}
res=next;
}
};