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.