[LeetCode 652] Find Duplicate Subtrees

Given a binary tree, return all duplicate subtrees. For each kind of duplicate subtrees, you only need to return the root node of any one of them.

Two trees are duplicate if they have the same structure with same node values.

Example 1:

        1
       / \
      2   3
     /   / \
    4   2   4
       /
      4

The following are two duplicate subtrees:

      2
     /
    4

and

    4

Therefore, you need to return above trees' root in the form of a list.

分析

这道题出的很新颖,刚开始的时候想直接进行左右子树的比对,如果不同,就在比较左子树的left,right和右子树对比,以及右子树的left,right与左子树的对比。但是这样的话比较难区分node是否已经有重复的出现在结果中了。

那么如何表征一个node节点呢?可以对该node进行序列化,只要保证node能够序列化和反序列化,那么序列化之后的string就可以表示这个node节点。所以就可以对比string是否已经存在。这样就可以直接用hash来进行判断。

对于node的序列化和反序列化,可以有很多的方式,参考 Serialize and Deserialize Binary Tree。在本题中我们只需要进行序列化就行了,那么可以用更简单的方式,例如:

        1
       / \
      2   3

可以使用前序遍历表示为:

1,2,#,#,3,#,#

对TreeNode的每一个节点进行序列化,并在map<>中寻找是否已经存在,如果不存在,则map[string] = 0;如果存在,判断map[string] == 0,不等于0说明之前已经有重复的了,就不用添加到结果中,如果==0,就添加到结果中

Code

class Solution {
public:
    vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
        vector<TreeNode*> res;
        map<string, int> m;
        serial(root, m, res);
        return res;
    }
    
    string serial(TreeNode* node, map<string, int>& m, vector<TreeNode*>& res)
    {
        if (node==NULL)
        {
            return "#";
        }
        
        string s = to_string(node->val) + "," + serial(node->left, m, res)
            + "," + serial(node->right, m, res);
        if (m.find(s) == m.end())
        {
            m[s] = 0;
        }
        else
        {
            if (m[s] == 0)
                res.push_back(node);
            m[s] ++;
        }
        return s;
    }
};

运行效率

Runtime: 48 ms, faster than 88.81% of C++ online submissions for Find Duplicate Subtrees.

Memory Usage: 51.8 MB, less than 36.46% of C++ online submissions forFind Duplicate Subtrees.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值