一、题目介绍
给定一棵二叉树,返回所有重复的子树。对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可。
两棵树重复是指它们具有相同的结构以及相同的结点值。
示例 1:
下面是两个重复的子树:
和 4
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-duplicate-subtrees
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、解题思路
本题利用序列化 + hash的方法来完成。
(1)首先自底向上给每一个子树进行序列化,序列化的过程是将某子树的根节点、其左子树序列化的结果、以及其右子树序列化的结果,组成一个字符字符串。这样可以保证相同的子树序列化之后得到相同的字符串。
(2)建立hash<string>类型的对象,将每个字符串进行hash计算(一定范围内能保证不同字符串获得不同结果),以hash结果和子树对应的结构体subTreeCount组成键值对存放在map中,如果有重复的子树在subTreeCount中记录出现的次数。
三、解题代码
struct subTreeCount
{
TreeNode* root;
int count;
};
class Solution {
public:
map<size_t, subTreeCount> mp;
hash<string> hasher;
vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
serialize(root);
vector<TreeNode*> res;
map<size_t, subTreeCount>::iterator it;
for(it = mp.begin(); it != mp.end(); ++it)
{
if((it->second).count > 1)
{
res.push_back((it->second).root);
}
}
return res;
}
size_t serialize(TreeNode* root)
{
if(root == NULL)
return hasher("[]");
char buf[2048];
sprintf(buf, "[%d,%d,%d]",root->val, serialize(root->left), serialize(root->right)); //序列化
size_t res = hasher(buf); //哈希计算
if(mp.count(res) == 0)
{
mp.insert(pair<size_t, subTreeCount>(res, {root, 1}));
}
else
{
mp[res].count++;
}
return res;
}
};