Problem Solving: How the serialize
function works (in Binary Tree)

The serialize
function can be useful in a variety of scenarios, some of which include:
- Duplicate Subtree Detection: As demonstrated in the problem solution we discussed earlier, the
serialize
function can be used to detect duplicate subtrees in a binary tree. - Tree Serialization and Deserialization: The
serialize
function can be used to serialize a binary tree into a string format that can be easily transmitted or stored in a file. This serialized format can then be used to reconstruct the original tree using a deserialization function. - Comparing Two Trees: The
serialize
function can be used to compare two trees for equality. By serializing both trees and comparing their resulting strings, we can determine if they have the same structure and values. - Caching: The
serialize
function can be used to cache the results of expensive operations performed on a tree. By serializing the tree and using the resulting string as a key in a cache, we can quickly retrieve the cached result for any subtree with the same structure and values. - Tree Compression: The
serialize
function can be used to compress a binary tree by converting it into a smaller string representation. This compressed representation can be transmitted or stored more efficiently than the original tree.
Here is an example of how the serialize
function works.
Suppose we have the following binary tree:
1
/ \
2 3
/ \ \
4 5 6
We call serialize
with the root of this tree, like this:
Example: Given the root of a binary tree, return all duplicate subtrees.
vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
unordered_map<string, int> m;
vector<TreeNode*> res;
serialize(root, m, res);
return res;
}
The serialize
function is called recursively for each node in the tree. Let's look at how it works for the root node (value 1):
string serialize(TreeNode* root, unordered_map<string, int>& m, vector<TreeNode*>& res) {
if (!root) {
return "#";
}
string s = to_string(root->val) + "," + serialize(root->left, m, res) + "," + serialize(root->right, m, res);
if (++m[s] == 2) {
res.push_back(root);
}
return s;
}
First, we check if the current node is null. If it is, we return the string "#"
. Otherwise, we recursively serialize the left and right subtrees of the current node, and concatenate them with the value of the current node to form a string s
. The resulting string for the root node is:
"1,2,4,#,#,5,#,#,3,#,6,#,#"
Next, we increment the count of this string in the map m
, and check if it is the second time we have seen this string. Since this is the first time we have seen it, the count is now 1, and we don't add the current node to the res
vector.
We then return the serialized string s
for the root node.
Next, the serialize
function is called for the left child of the root node (value 2). The resulting string is:
"2,4,#,#,5,#,#"
Since this is the first time we have seen this string, we increment the count to 1, and don’t add the current node to the res
vector.
The serialize
function is then called for the right child of the root node (value 3). The resulting string is:
"3,#,6,#,#"
Again, since this is the first time we have seen this string, we increment the count to 1, and don’t add the current node to the res
vector.
The serialize
function is then called recursively for the left subtree of the root node (value 2). The resulting string is:
"4,#,#"
Since this is the first time we have seen this string, we increment the count to 1, and don’t add the current node to the res
vector.
The serialize
function is then called recursively for the right subtree of the root node (value 2). The resulting string is:
"5,#,#"
Since this is the first time we have seen this string, we increment the count to 1, and don’t add the current node to the res
vector.
The serialize
function is then called recursively for the right subtree of the root node (value 3). The resulting string is:
"6,#,#"
Since this is the first time we have seen this string, we increment the count to 1, and don’t add the current node to the res
vector.
After all nodes have been processed, the res
vector contains all the root nodes of the duplicate subtrees. In this case, there are no duplicate subtrees, so res
is empty.
The findDuplicateSubtrees
function then returns the res
vector.