LeetCode 572. 另一个树的子树(暴力或kmp)
题目
给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树。s 的一个子树包括 s 的一个节点和这个节点的所有子孙。s 也可以看做它自身的一棵子树。
样例
方法一:DFS暴力
按照dfs序查找s树中每一个节点的节点,某个节点值等于t数的根节点,判断该节点的子树是否等于t
class Solution
{
public:
bool check(TreeNode* a,TreeNode* b)
{
if(!a&&!b) return true;
if((!a&&b)||(!b&&a)||a->val!=b->val) return false;
return check(a->left,b->left) && check(a->right,b->right);
}
bool dfs(TreeNode* now,TreeNode* find)
{
if (!now) return false;
return check(now,find) || dfs(now->left,find) || dfs(now->right,find);
}
bool isSubtree(TreeNode* s, TreeNode* t)
{
return dfs(s,t);
}
};
时间复杂度为
O
(
∣
s
∣
×
∣
t
∣
)
O(|s|\times|t|)
O(∣s∣×∣t∣)
空间复杂度为
O
(
m
a
x
(
∣
s
∣
,
∣
t
∣
)
)
O(max(|s|,|t|))
O(max(∣s∣,∣t∣))
方法二:kmp字符串匹配
把
s
s
s树和
t
t
t数按照dfs序展开成数组
s
s
ss
ss和
t
t
tt
tt。
引入两个数
l
n
u
l
l
lnull
lnull,
r
n
u
l
l
rnull
rnull,用于没有左右节点的数。
l
n
u
l
l
=
0
x
3
f
3
f
3
f
3
f
lnull=0x3f3f3f3f
lnull=0x3f3f3f3f
r
n
u
l
l
=
0
x
3
f
3
f
3
f
3
f
+
1
rnull=0x3f3f3f3f+1
rnull=0x3f3f3f3f+1
转换为数组后只要判断
t
t
tt
tt是不是
s
s
ss
ss的子串就可以了,这个可以用kmp算法实现
class Solution
{
public:
vector<int>ss[2];
vector<int>f;
int lnull=0x3f3f3f3f,rnull=0x3f3f3f3f+1;
void get(TreeNode* now,int i)
{
if(!now) return;
ss[i].push_back(now->val);
if(now->left) get(now->left,i);
else ss[i].push_back(lnull);
if(now->right) get(now->right,i);
else ss[i].push_back(rnull);
}
void getf(int m)
{
f[0]=-1;
for(int i=1;i<m;i++)
{
int j=f[i-1];
while ((ss[1][j+1]!=ss[1][i])&&(j>=0))
j=f[j];
if (ss[1][j+1]==ss[1][i]) f[i]=j+1;
else f[i]=-1;
}
}
bool kmp(int n,int m)
{
int i=0,j=0;
while(i<n)
{
if(ss[0][i]==ss[1][j])
{
i++;
j++;
if(j==m)
{
return true;
j=f[j-1]+1;
}
}
else
{
if (j==0) i++;
else j=f[j-1]+1;
}
}
return false;
}
bool isSubtree(TreeNode* s, TreeNode* t)
{
get(s,0);
get(t,1);
f.resize(ss[1].size()+1);
getf(ss[1].size());
return kmp(ss[0].size(),ss[1].size());
}
};
时间复杂度为
O
(
∣
s
∣
+
∣
t
∣
)
O(|s|+|t|)
O(∣s∣+∣t∣)
空间复杂度为
O
(
∣
s
∣
+
∣
t
∣
)
O(|s|+|t|)
O(∣s∣+∣t∣)