Skip to content

Commit b7dd8ac

Browse files
authored
Update find-duplicate-subtrees.cpp
1 parent a01658a commit b7dd8ac

File tree

1 file changed

+91
-2
lines changed

1 file changed

+91
-2
lines changed

C++/find-duplicate-subtrees.cpp

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// Time: O(n * h)
2-
// Space: O(n * h)
1+
// Time: O(n)
2+
// Space: O(n)
33

44
/**
55
* Definition for a binary tree node.
@@ -10,7 +10,96 @@
1010
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
1111
* };
1212
*/
13+
14+
namespace std{
15+
namespace
16+
{
17+
18+
// Code from boost
19+
// Reciprocal of the golden ratio helps spread entropy
20+
// and handles duplicates.
21+
// See Mike Seymour in magic-numbers-in-boosthash-combine:
22+
// http://stackoverflow.com/questions/4948780
23+
24+
template <class T>
25+
inline void hash_combine(std::size_t& seed, T const& v)
26+
{
27+
seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
28+
}
29+
30+
// Recursive template code derived from Matthieu M.
31+
template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1>
32+
struct HashValueImpl
33+
{
34+
static void apply(size_t& seed, Tuple const& tuple)
35+
{
36+
HashValueImpl<Tuple, Index-1>::apply(seed, tuple);
37+
hash_combine(seed, std::get<Index>(tuple));
38+
}
39+
};
40+
41+
template <class Tuple>
42+
struct HashValueImpl<Tuple,0>
43+
{
44+
static void apply(size_t& seed, Tuple const& tuple)
45+
{
46+
hash_combine(seed, std::get<0>(tuple));
47+
}
48+
};
49+
}
50+
51+
template <typename ... TT>
52+
struct hash<std::tuple<TT...>>
53+
{
54+
size_t
55+
operator()(std::tuple<TT...> const& tt) const
56+
{
57+
size_t seed = 0;
58+
HashValueImpl<std::tuple<TT...> >::apply(seed, tt);
59+
return seed;
60+
}
61+
62+
};
63+
}
64+
1365
class Solution {
66+
public:
67+
vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
68+
unordered_map<int, vector<TreeNode *>> trees;
69+
unordered_map<tuple<int, int, int>, int> lookup;
70+
getid(root, &lookup, &trees);
71+
72+
vector<TreeNode *> result;
73+
for (const auto& kvp : trees) {
74+
if (kvp.second.size() > 1) {
75+
result.emplace_back(kvp.second[0]);
76+
}
77+
}
78+
return result;
79+
}
80+
81+
private:
82+
int getid(TreeNode *root,
83+
unordered_map<tuple<int, int, int>, int> *lookup,
84+
unordered_map<int, vector<TreeNode *>> *trees) {
85+
auto node_id = 0;
86+
if (root) {
87+
const auto& data = make_tuple(root->val,
88+
getid(root->left, lookup, trees),
89+
getid(root->right, lookup, trees));
90+
if (!lookup->count(data)) {
91+
(*lookup)[data] = lookup->size() + 1;
92+
}
93+
node_id = (*lookup)[data];
94+
(*trees)[node_id].emplace_back(root);
95+
}
96+
return node_id;
97+
}
98+
};
99+
100+
// Time: O(n * h)
101+
// Space: O(n * h)
102+
class Solution2 {
14103
public:
15104
vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
16105
unordered_map<string, int> lookup;

0 commit comments

Comments
 (0)