Duplicate Subtrees | Practice | GeeksforGeeks

Given a binary tree of size N, your task is to that find all duplicate subtrees from the given binary tree.

Example:
Input : 

Output : 2 4
         4
Explanation: Above Trees are two 
duplicate subtrees.i.e  and 
Therefore,you need to return above trees 
root in the form of a list.
Your Task:
You don't need to take input. Just complete the function printAllDups() that takes the root node as a parameter and returns an array of Node*, which contains all the duplicate subtree.
Note: Here the Output of every Node printed in the Pre-Order tree traversal format.

Constraints:
1<=T<=100
1<=N<=100
+1
shilsoumyadip3 weeks ago
c++ code 
 
 
unordered_map<string, int>m;vector <Node*> v;string solve(Node*root){   if(!root) return " ";   string s = " ";   if(!root->left and !root->right)   {       s = to_string(root->data);       m[s]++;          }      s = s + to_string(root->data);   s = s + solve(root->left);   s = s + solve(root->right);       if (m[s] == 1)        v.push_back (root);             m[s]++;   return s;   }vector<Node*> printAllDups(Node* root){   // Code here   m.clear();   v.clear();   solve(root);   return v;}
+4
gaurabhkumarjha271020011 month ago
  // simple c++ code
  vector <Node*> v;
 unordered_map <string, int> m;
 string solve (Node* root){
     
     if (!root) return "";
     
     string left= solve (root->left);
     string right= solve (root->right);
     
string ans= to_string(root->data)+ "$"+left+"$"+ right;
     
       
       if (m[ans] == 1)
         v.push_back (root);
         
        m[ans]++; 
         
      return ans;
 }
vector<Node*> printAllDups(Node* root)
{
    // Code here
    m.clear();
    v.clear();
     solve (root);
     
     return v;
}
+2
sanketbhagat2 months ago
SIMPLE JAVA SOLUTION
class Solution{
    String solve(Node root, Map<String,Integer> map, List<Node> list){
        if(root==null) return "";
        String l = solve(root.left,map,list);
        String r = solve(root.right,map,list);
        String str = l+"#"+root.data+"#"+r;
        map.put(str,map.getOrDefault(str,0)+1);
        if(map.get(str)==2) list.add(root);
        return str;
    }
  
    public List<Node> printAllDups(Node root){
       //code here
       Map<String,Integer> map = new HashMap<>();
       List<Node> list = new ArrayList<>();
       solve(root,map,list);
       return list;
    }
}
0
aloksinghbais022 months ago
C++ solution having time complexity as O(N) and space complexity as O(N) is as follows :- 
 
Execution Time :- 0.0 / 2.2 sec
 
unordered_map<string,int> mp;vector<Node*> ans;
string postorder(Node *node){   if(!node) return ("$");   string s1 = postorder(node->left);   string s2 = postorder(node->right);      string res{};   res = s1 + to_string(node->data) + s2;   mp[res]++;   if(mp[res] == 2) ans.push_back(node);   return (res);}
vector<Node*> printAllDups(Node* root){   mp.clear();   ans.clear();   postorder(root);   return (ans);}
0
manishmaheshwari81333 months ago
JAVA CODE
class Solution{
         HashMap<String,Integer> map=new HashMap<>();
         ArrayList<Node> arr=new ArrayList<>();
    
String containdub(Node node){
    if(node==null)return "$";
    String str ="";

    str=str+String.valueOf(node.data)+"*";
    str=str+containdub(node.left)+"*";
    str=str+containdub(node.right);
    
        if(map.containsKey(str)==true) {
			 int of=map.get(str);
			 int nf=of+1;
			 map.put(str, nf);
				   
		}else {
			map.put(str, 1);
		}
	
	if(map.get(str)==2) arr.add(node);

    return str;
     }
     
     
    public List<Node> printAllDups(Node root)
    {
       containdub(root);
       return arr;
    }
}
0
geekygaurab3 months ago
C++ solution that uses the logic that two duplicate subtrees shall have the same preorder traversal. Map is used to get to potentially duplicate subtrees for a particular tree (having same value in the root nodes) in O(1) time.
 
IMPORTANT → The nodes are to be returned in postorder fashion to match the generated results by GFG (not mentioned in problem statement as of 19-1-2022).
 
Time complexity → O(N^2) and space → O(N).
Execution time → 0.0/2.2
 
void populateMapInLevelOrder(Node* root, unordered_map<int, queue<Node*>> &mp)
{
    queue<Node*> q;
    
    if(root->left!=nullptr)
    {
        q.push(root->left);
    }
    if(root->right!=nullptr)
    {
        q.push(root->right);
    }
    
    while(!q.empty())
    {
        Node* p = q.front();
        q.pop();
        
        mp[p->data].push(p);
        
        if(p->left!=nullptr)
        {
            q.push(p->left);
        }
        if(p->right!=nullptr)
        {
            q.push(p->right);
        }
    }
}

void recurPreorder(Node* root, vector<int> &ans)
{
    if(root!=nullptr)
    {
        ans.push_back(root->data);
        recurPreorder(root->left, ans);
        recurPreorder(root->right, ans);
    }
}

bool areDupSubtrees(Node* p, Node* q)
{
    vector<int> vec1, vec2;
    
    recurPreorder(p, vec1);
    recurPreorder(q, vec2);
    
    if(vec1.size()!=vec2.size())
    {
        return false;
    }
    
    for(int i=0 ; i<vec1.size() ; i++)
    {
        if(vec1[i]!=vec2[i])
        {
            return false;
        }
    }
    
    return true;
}

void findDupSubtreesInPostOrder(Node* p, unordered_map<int, queue<Node*>> &mp, vector<Node*> &ans)
{
    if(p!=nullptr)
    {
        findDupSubtreesInPostOrder(p->left, mp, ans);
        
        findDupSubtreesInPostOrder(p->right, mp, ans);
        
        int n = mp[p->data].size();
        
        bool insertedOnceInAns = false;
        
        while(n--)
        {
            Node* r = mp[p->data].front();
            mp[p->data].pop();
            
            if(p==r)
            {
                continue;
            }
            
            if(areDupSubtrees(p,r))
            {
                if(!insertedOnceInAns)
                {
                    ans.push_back(p);
                    insertedOnceInAns = !insertedOnceInAns;
                }
            }
            else
            {
                mp[p->data].push(r);
            }
        }
    }
}

vector<Node*> printAllDups(Node* root)
{
    unordered_map<int, queue<Node*>> mp;
    
    populateMapInLevelOrder(root, mp);
    
    vector<Node*> ans;
    
    findDupSubtreesInPostOrder(root, mp, ans);
    
    return ans;
}
 
Thanks!
-1
sangamchoudhary74 months ago
2 Approach 
 
Time - O(n^2) and Space - O(4n)
Time - O(n^2) and Space - O(4n)
    void postorder(Node* root,vector<int> &temp){
        if(!root){
            temp.push_back(-100000);
            return;
        }
        
        postorder(root->left,temp);
        postorder(root->right,temp);
        temp.push_back(root->data);
    }
    
    void dfs(Node* root,map<vector<int>,int> &mp,vector<Node*> &ans){
        if(!root) return;
        dfs(root->left,mp,ans);
        dfs(root->right,mp,ans);
        vector<int> temp;
        postorder(root,temp);
        if(temp.size() > 0){
            mp[temp]++;
            if(mp[temp] == 2){
                ans.push_back(root);
            }
        }
    }
    
    vector<Node*> printAllDups(Node* root) {
        map<vector<int>,int> map;
        vector<Node*> ans;
        dfs(root,map,ans);
        return ans;
    }
2. Time - O(n) and Space - O(3n)
        vector<Node*> vec;
        unordered_map<string,int> ump;
        string solve(Node* root){
            if(!root) return "$";
            string left = solve(root->left);
            string right = solve(root->right);
            string s = to_string(root->val) +"$"+left+"$"+right;
            if(ump[s]==1){
                vec.push_back(root);
            }
            ump[s]++;
            return s;
        }
        vector<Node*> findDuplicateSubtrees(Node* root) {
            if(!root) return vec;
            solve(root);
            return vec;
        }
0
chessnoobdj4 months ago
Easy c++
string DFS(Node* root, unordered_map<string, int>& m, vector<Node*>& res){
    if(!root) return "";
    string s = to_string(root->data) + "R"
                + DFS(root->right, m, res) + "L" 
                + DFS(root->left, m, res);
    if(m[s]++ == 1) res.push_back(root);
    return s;
}

vector<Node*> printAllDups(Node* root)
{
    unordered_map <string, int> m;
    vector <Node*> res;
    DFS(root, m, res);
    return res;
}
0
akramdevstuffs4 months ago
Using hashing with map in C++ code.
// A helper function for getting Duplicates subtrees using recursion
string subTreeDups(Node* root, unordered_map<string, int>& mp, vector<Node*>& ans) {
    if (!root)
        return "";
    // Store the string in preorder
    string res = to_string(root->data);
    res += '(';
    res += subTreeDups(root->left, mp, ans);
    res += ')';
    res += '(';
    res += subTreeDups(root->right, mp, ans);
    res += ')';
    // Subtree already present (Note that we use
    // unordered_map instead of unordered_set
    // because we want to print multiple duplicates
    // only once, consider example of 4 in above
    // subtree, it should be printed only once.
    if (mp[res] == 1)
        ans.push_back(root);
    mp[res]++;
    return res;
}

// you are required to complete this function
// the function and return an vector of Node
// which contains all the duplicate sub-tree
vector<Node*> printAllDups(Node* root)
{
    // Code here
    vector<Node*> ans;
    unordered_map<string, int> mp; // For hashing the subtrees
    subTreeDups(root, mp, ans);
    return ans;
}
-1
ashutoshrastogi4 months ago
Java Code
 
class Solution{
    HashMap<String, Integer> hs = new HashMap<>();
    
    ArrayList<Node> ar = new ArrayList<>();
    
    public List<Node> printAllDups(Node root)
    {
        hs.clear();
        ar.clear();
        solve(root);
        return ar;
    }
    
    String solve(Node n){
        if(n==null)
            return "";
        String s = "";   
        
        s += String.valueOf(n.data);
        s += " ";
        
        s += solve(n.left);
        s+= " ";
        
        s += solve(n.right);
        s+= " ";

        
        checkexist(s, n);
        return s;
    }
    
    
    void checkexist(String s, Node n){
        if(hs.containsKey(s) && hs.get(s)==1){
            ar.add(n);
            hs.put(s,2);
        }
        else
            hs.put(s,1);
    }
    
}
We strongly recommend solving this problem on your own before viewing its editorial. Do you still
                    want to view the editorial?
 Login to access your submissions. 

Problem


Contest

Reset the IDE using the second button on the top right corner.
Avoid using static/global variables in your code as your code is tested against multiple test cases and these tend to retain their previous values.
Passing the Sample/Custom Test cases does not guarantee the correctness of code. On submission, your code is tested against multiple test cases consisting of all possible corner cases and stress constraints.
You can access the hints to get an idea about what is expected of you as well as the final solution code.
You can view the solutions submitted by other users from the submission tab.