572. Subtree of Another Tree (另一个树的子树)

Given two non-empty binary trees s and t, check whether tree t has exactly the same structure and node values with a subtree of s. A subtree of s is a tree consists of a node in s and all of this node’s descendants. The tree scould also be considered as a subtree of itself.

Example 1:
Given tree s:

 3
/ \

4 5
/ \
1 2
Given tree t:

4
/ \
1 2
Return true, because t has the same structure and node values with a subtree of s.

Example 2:
Given tree s:

 3
/ \

4 5
/ \
1 2
/
0
Given tree t:

4
/ \
1 2
Return false.

这道题让我们求一个数是否是另一个树的子树,从题目中的第二个例子中可以看出,子树必须是从叶结点开始的,中间某个部分的不能算是子树,那么我们转换一下思路,是不是从s的某个结点开始,跟t的所有结构都一样,那么问题就转换成了判断两棵树是否相同,也就是Same Tree的问题了,这点想通了其实代码就很好写了,用递归来写十分的简洁,我们先从s的根结点开始,跟t比较,如果两棵树完全相同,那么返回true,否则就分别对s的左子结点和右子结点调用递归再次来判断是否相同,只要有一个返回true了,就表示可以找得到。

解法一:

class Solution {
public:
    bool isSubtree(TreeNode* s, TreeNode* t) {
        if (!s) return false;
        if (isSame(s, t)) return true;
        return isSubtree(s->left, t) || isSubtree(s->right, t);
    }
    bool isSame(TreeNode* s, TreeNode* t) {
        if (!s && !t) return true;
        if (!s || !t) return false;
        if (s->val != t->val) return false;
        return isSame(s->left, t->left) && isSame(s->right, t->right);
    }
};

下面这道题的解法用到了之前那道Serialize and Deserialize Binary Tree的解法,思路是对s和t两棵树分别进行序列化,各生成一个字符串,如果t的字符串是s的子串的话,就说明t是s的子树,但是需要注意的是,为了避免出现[12], [2], 这种情况,虽然2也是12的子串,但是[2]却不是[12]的子树,所以我们再序列化的时候要特殊处理一下,就是在每个结点值前面都加上一个字符,比如’,’,来分隔开,那么[12]序列化后就是”,12,#”,而[2]序列化之后就是”,2,#”,这样就可以完美的解决之前的问题了,参见代码如下:

解法二:

class Solution {
public:
    bool isSubtree(TreeNode* s, TreeNode* t) {
        ostringstream os1, os2;
        serialize(s, os1);
        serialize(t, os2);
        return os1.str().find(os2.str()) != string::npos; 
        /*string::npos作为string的成员函数的一个长度参数时,
        表示“直到字符串结束(until the end of the string)”
        */
    }
    void serialize(TreeNode* node, ostringstream& os) {
        if (!node) os << ",#";
        else {
            os << "," << node->val;
            serialize(node->left, os);
            serialize(node->right, os);
        }
    }
};

笔记:递归调用;第二种方法将问题进行了转化,比较巧妙。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值