LeetCode 572. 另一个树的子树(暴力或kmp)

LeetCode 572. 另一个树的子树(暴力或kmp)

题目

给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树。s 的一个子树包括 s 的一个节点和这个节点的所有子孙。s 也可以看做它自身的一棵子树。

样例

LeetCode 572. 另一个树的子树(暴力或kmp)_第1张图片LeetCode 572. 另一个树的子树(暴力或kmp)_第2张图片


方法一: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)

你可能感兴趣的:(LeetCode 572. 另一个树的子树(暴力或kmp))