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

Rambabu Yerajana
4 min readFeb 28, 2023

The serialize function can be useful in a variety of scenarios, some of which include:

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

No responses yet

Write a response