572. Subtree of Another Tree

406 篇文章 0 订阅
406 篇文章 0 订阅

1,题目要求
判断一棵树是否是另一棵树的子树。
这里写图片描述
这里写图片描述
需要注意的是,这里的子树不是含有就是子树,要求原树中的子树部分不能有其他节点,就像example2中所说的那样。

2,题目思路
一开始,想象直接对s进行中序遍历,如果有节点的值和t的节点的值相同,就直接判断该s节点的左右节点的值是否和t左右节点的值相同。另外一种思路就是将s和t完全中序遍历并存储在向量中,然后做一个相同判断。
上述两种办法都不能不能解决example2中的问题,仅仅能判断t是否在s之中,因此都不可行。
参考了别人的代码,有以下方法:
核心还是递归的思想,新建一个子树是否相同的递归函数。然后在主函数体中进行递归的调用,依次对s中的每个节点与树t做相同判断。

3,程序源码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isSubtree(TreeNode* s, TreeNode* t) {
        if(s == NULL) return false;
        if(isSame(s,t)) return true;
        return isSubtree(s->left, t) || isSubtree(s->right, t);
    }

private:
    bool isSame(TreeNode* s,TreeNode* t)   //判断两棵树是否相同
    {
        if(s == NULL&& t == NULL)
            return true;
        if(s == NULL|| t == NULL)
            return false;
        if(s->val != t->val)
            return false;
        return isSame(s->left, t->left) && isSame(s->right, t->right);
    }
};

这种方法还有一种改进的方式,即在对s的遍历是暴力的——要遍历s中的所有的节点。
优化的方式便是只对那些最大高度跟t相同的s节点进行比照。最大高度大于t的一定不可能是s的子树。

class Solution {
    vector<TreeNode*> nodes;
public:
    bool isSubtree(TreeNode* s, TreeNode* t) {
        if (!s && !t) return true;
        if (!s || !t) return false;

        getDepth(s, getDepth(t, -1));  //将s中最大深度等于t的节点找出并按次序push
        到nodes向量中

        for (TreeNode* n: nodes)
            if (identical(n, t))
                return true;

        return false;
    }

    int getDepth(TreeNode* r, int d) {
        if (!r)
            return -1;

        int depth = max(getDepth(r->left, d), getDepth(r->right, d)) + 1;

        // 对该节点所在的最大深度做判断
        // -1只是为了找出t的最大高度,不需要讲其push到判断向量中
        if (depth == d)
            nodes.push_back(r);

        return depth;
    }

    bool identical(TreeNode* a, TreeNode* b) {
        if (!a && !b) return true;
        if (!a || !b || a->val != b->val) return false;

        return identical(a->left, b->left) && identical(a->right, b->right);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值