Given the root of an n-ary tree, the task is to find the number of subtrees that have duplicates in the n-ary tree. Two trees are duplicates if they have the same structure with the same node values.
Examples:
Input: root = [1, N, 2, 2, 3, N, 4, N, 4, 4, 3, N, N N N N] Output: 2 Explanation: [4], [3] are duplicate subtree.
Input: root = [1, N, 2, 3, N, 4, 5, 6, N, N, N, N] Output: 0 Explanation: No duplicate subtree found.
[Naive Approach] Using Serialization + Hash Map - O(N²) Time and O(N) Space
The idea is to serialize every subtree of the N-ary tree into a unique string representation using DFS traversal. For each node, its value and the serialized forms of all its children are combined to form a subtree string. A hash map is used to store the frequency of every serialized subtree. After traversing the entire tree, all subtree serializations having frequency greater than 1 are counted as duplicate subtrees. Since string concatenation is performed repeatedly for every subtree, the overall complexity can reach O(N²) in the worst case.
Perform DFS traversal on the tree
Serialize each subtree into a string
Store subtree frequency in a hash map
Traverse the map: Count all subtree strings with frequency greater than 1
Return the total duplicate subtree count
C++
// C++ code to implement the approach#include<bits/stdc++.h>usingnamespacestd;// Structure of a tree nodeclassNode{public:intdata;vector<Node*>children;Node(intval){data=val;}};stringdfs(Node*root,unordered_map<string,int>&f){// Base conditionif(root==0)return"";strings="(";s+=to_string(root->data);// Dfs call for all childrenfor(autochild:root->children){s+=dfs(child,f);}s+=')';f[s]++;// Return answer stringreturns;}// Function to count number of duplicate subtreesintcountDupSubtrees(Node*root){// Declare a mapunordered_map<string,int>f;// DFS calldfs(root,f);intans=0;// Loop for traversing the mapfor(autop:f)if(p.second>1)ans++;// Return the count of duplicate subtreesreturnans;}// Driver codeintmain(){Node*root=newNode(1);root->children.push_back(newNode(2));root->children.push_back(newNode(2));root->children.push_back(newNode(3));root->children[0]->children.push_back(newNode(4));root->children[1]->children.push_back(newNode(4));root->children[1]->children.push_back(newNode(4));root->children[1]->children.push_back(newNode(3));cout<<countDupSubtrees(root);return0;}
Java
// Java program to count duplicate subtrees in an N-ary treeimportjava.util.*;classNode{intdata;List<Node>children;Node(intval){data=val;children=newArrayList<>();}}classGfG{staticStringdfs(Noderoot,Map<String,Integer>freq){// Base conditionif(root==null)return"";Strings="("+root.data;// DFS call for all childrenfor(Nodechild:root.children){s+=dfs(child,freq);}s+=")";freq.put(s,freq.getOrDefault(s,0)+1);// Return answer stringreturns;}// Function to count number of duplicate subtreesstaticintcountDupSubtrees(Noderoot){// Declare a mapMap<String,Integer>freq=newHashMap<>();// DFS calldfs(root,freq);intans=0;// Loop for traversing the mapfor(intcount:freq.values()){if(count>1)ans++;}// Return the count of duplicate subtreesreturnans;}publicstaticvoidmain(String[]args){Noderoot=newNode(1);root.children.add(newNode(2));root.children.add(newNode(2));root.children.add(newNode(3));root.children.get(0).children.add(newNode(4));root.children.get(1).children.add(newNode(4));root.children.get(1).children.add(newNode(4));root.children.get(1).children.add(newNode(3));System.out.println(countDupSubtrees(root));}}
Python
# Python program to count duplicate subtrees in an N-ary treeclassNode:def__init__(self,key,children=None):self.key=keyself.children=childrenor[]def__str__(self):returnstr(self.key)classSolution:defdfs(self,root,f):# Base conditionifrootisNone:return""s="("+str(root.key)# DFS call for all childrenforchildinroot.children:s+=self.dfs(child,f)s+=")"f[s]=f.get(s,0)+1# Return answer stringreturnsdefcountDupSubtrees(self,root):# Declare a dictionaryf={}# DFS callself.dfs(root,f)ans=0# Loop for traversing the dictionaryforcountinf.values():ifcount>1:ans+=1# Return the count of duplicate subtreesreturnans# Driver codeif__name__=="__main__":# Building the treeroot=Node(1)root.children=[Node(2),Node(2),Node(3)]root.children[0].children=[Node(4)]root.children[1].children=[Node(4),Node(4),Node(3)]sol=Solution()print(sol.countDupSubtrees(root))
C#
// C# program to count duplicate subtrees in an N-ary treeusingSystem;usingSystem.Collections.Generic;classNode{publicintdata;publicList<Node>children;publicNode(intval){data=val;children=newList<Node>();}}classGfG{staticstringdfs(Noderoot,Dictionary<string,int>freq){// Base conditionif(root==null)return"";strings="("+root.data;// DFS call for all childrenforeach(Nodechildinroot.children){s+=dfs(child,freq);}s+=")";if(freq.ContainsKey(s))freq[s]++;elsefreq[s]=1;// Return answer stringreturns;}// Function to count number of duplicate subtreesstaticintcountDupSubtrees(Noderoot){// Declare a dictionaryDictionary<string,int>freq=newDictionary<string,int>();// DFS calldfs(root,freq);intans=0;// Loop for traversing the dictionaryforeach(intcountinfreq.Values){if(count>1)ans++;}// Return the count of duplicate subtreesreturnans;}staticvoidMain(string[]args){Noderoot=newNode(1);root.children.Add(newNode(2));root.children.Add(newNode(2));root.children.Add(newNode(3));root.children[0].children.Add(newNode(4));root.children[1].children.Add(newNode(4));root.children[1].children.Add(newNode(4));root.children[1].children.Add(newNode(3));Console.WriteLine(countDupSubtrees(root));}}
JavaScript
// JavaScript program to count duplicate subtrees in an N-ary treeclassNode{constructor(val){this.data=val;this.children=[];}}functiondfs(root,freq){// Base conditionif(root===null)return"";lets="("+root.data;// DFS call for all childrenfor(letchildofroot.children){s+=dfs(child,freq);}s+=")";freq.set(s,(freq.get(s)||0)+1);// Return answer stringreturns;}// Function to count number of duplicate subtreesfunctioncountDupSubtrees(root){// Declare a mapletfreq=newMap();// DFS calldfs(root,freq);letans=0;// Loop for traversing the mapfor(letcountoffreq.values()){if(count>1)ans++;}// Return the count of duplicate subtreesreturnans;}// Driver codeconstroot=newNode(1);root.children.push(newNode(2));root.children.push(newNode(2));root.children.push(newNode(3));root.children[0].children.push(newNode(4));root.children[1].children.push(newNode(4));root.children[1].children.push(newNode(4));root.children[1].children.push(newNode(3));console.log(countDupSubtrees(root));
Output
2
[Expected Approach] Using Hashing + DFS - O(N) Average Time and O(N) Space
The idea is to generate a hash value for every subtree instead of storing complete serialized strings. During DFS traversal, the hash of each child subtree is combined with the current node value to create a unique hash representing the entire subtree. A hash map stores the frequency of every subtree hash. After traversal, all hashes appearing more than once represent duplicate subtrees. Since hashing avoids repeated large string constructions, this approach works much faster on average compared to serialization.
Perform DFS traversal on the N-ary tree
Compute hash value for every subtree
Combine child hashes with current node value
Store subtree hash frequency in a hash map
Count all hashes having frequency greater than 1
Return the duplicate subtree count
C++
// C++ code to implement the approach#include<bits/stdc++.h>usingnamespacestd;// Structure of a tree nodeclassNode{public:intdata;vector<Node*>children;Node(intval){data=val;}};// DFS function for hashinglonglongdfs(Node*root,unordered_map<longlong,int>&f){// Base conditionif(root==NULL)return7;// Start hash with node valuelonglongh=root->data;// DFS for all childrenfor(autochild:root->children){longlongchildHash=dfs(child,f);// Combine hashesh=h*31+childHash*17;}// Store subtree hash frequencyf[h]++;// Return subtree hashreturnh;}// Function to count duplicate subtreesintcountDupSubtrees(Node*root){// Hash frequency mapunordered_map<longlong,int>f;// DFS calldfs(root,f);intans=0;// Count duplicate subtree hashesfor(autox:f){if(x.second>1)ans++;}// Return answerreturnans;}// Driver codeintmain(){// Building treeNode*root=newNode(1);root->children.push_back(newNode(2));root->children.push_back(newNode(2));root->children.push_back(newNode(3));root->children[0]->children.push_back(newNode(4));root->children[1]->children.push_back(newNode(4));root->children[1]->children.push_back(newNode(4));root->children[1]->children.push_back(newNode(3));// Function callcout<<countDupSubtrees(root);return0;}
Java
// Java program to count duplicate subtrees in an N-ary tree using hashingimportjava.util.*;classNode{intdata;List<Node>children;Node(intval){data=val;children=newArrayList<>();}}classGfG{// DFS function for hashingstaticlongdfs(Noderoot,Map<Long,Integer>freq){// Base conditionif(root==null)return7;// Start hash with node valuelongh=root.data;// DFS for all childrenfor(Nodechild:root.children){longchildHash=dfs(child,freq);// Combine hashesh=h*31+childHash*17;}// Store subtree hash frequencyfreq.put(h,freq.getOrDefault(h,0)+1);// Return subtree hashreturnh;}// Function to count duplicate subtreesstaticintcountDupSubtrees(Noderoot){// Hash frequency mapMap<Long,Integer>freq=newHashMap<>();// DFS calldfs(root,freq);intans=0;// Count duplicate subtree hashesfor(intcount:freq.values()){if(count>1)ans++;}// Return answerreturnans;}publicstaticvoidmain(String[]args){// Building treeNoderoot=newNode(1);root.children.add(newNode(2));root.children.add(newNode(2));root.children.add(newNode(3));root.children.get(0).children.add(newNode(4));root.children.get(1).children.add(newNode(4));root.children.get(1).children.add(newNode(4));root.children.get(1).children.add(newNode(3));// Function callSystem.out.println(countDupSubtrees(root));}}
Python
# Python program to count duplicate subtrees in an N-ary tree using hashing''' Structure of an n-ary tree node '''classNode:def__init__(self,key,children=None):self.key=keyself.children=childrenor[]def__str__(self):returnstr(self.key)classSolution:# DFS function for hashingdefdfs(self,root,freq):# Base conditionifrootisNone:return7# Start hash with node keyh=root.key# DFS for all childrenforchildinroot.children:childHash=self.dfs(child,freq)# Combine hashesh=h*31+childHash*17# Store subtree hash frequencyfreq[h]=freq.get(h,0)+1# Return subtree hashreturnh# Function to count duplicate subtreesdefcountDupSubtrees(self,root):# Hash frequency mapfreq={}# DFS callself.dfs(root,freq)ans=0# Count duplicate subtree hashesforcountinfreq.values():ifcount>1:ans+=1# Return answerreturnans# Driver codeif__name__=="__main__":# Building treeroot=Node(1)# Adding children to rootnode2_1=Node(2)node2_2=Node(2)node3=Node(3)root.children=[node2_1,node2_2,node3]# Adding children to first node2node2_1.children=[Node(4)]# Adding children to second node2node2_2.children=[Node(4),Node(4),Node(3)]# Creating Solution object and calling functionsol=Solution()print(sol.countDupSubtrees(root))
C#
// C# program to count duplicate subtrees in an N-ary tree using hashingusingSystem;usingSystem.Collections.Generic;classNode{publicintdata;publicList<Node>children;publicNode(intval){data=val;children=newList<Node>();}}classGfG{// DFS function for hashingstaticlongdfs(Noderoot,Dictionary<long,int>freq){// Base conditionif(root==null)return7;// Start hash with node valuelongh=root.data;// DFS for all childrenforeach(Nodechildinroot.children){longchildHash=dfs(child,freq);// Combine hashesh=h*31+childHash*17;}// Store subtree hash frequencyif(freq.ContainsKey(h))freq[h]++;elsefreq[h]=1;// Return subtree hashreturnh;}// Function to count duplicate subtreesstaticintcountDupSubtrees(Noderoot){// Hash frequency mapDictionary<long,int>freq=newDictionary<long,int>();// DFS calldfs(root,freq);intans=0;// Count duplicate subtree hashesforeach(intcountinfreq.Values){if(count>1)ans++;}// Return answerreturnans;}staticvoidMain(string[]args){// Building treeNoderoot=newNode(1);root.children.Add(newNode(2));root.children.Add(newNode(2));root.children.Add(newNode(3));root.children[0].children.Add(newNode(4));root.children[1].children.Add(newNode(4));root.children[1].children.Add(newNode(4));root.children[1].children.Add(newNode(3));// Function callConsole.WriteLine(countDupSubtrees(root));}}
JavaScript
// JavaScript program to count duplicate subtrees in an N-ary tree using hashingclassNode{constructor(val){this.data=val;this.children=[];}}// DFS function for hashingfunctiondfs(root,freq){// Base conditionif(root===null)return7;// Start hash with node valueleth=root.data;// DFS for all childrenfor(letchildofroot.children){letchildHash=dfs(child,freq);// Combine hashesh=h*31+childHash*17;}// Store subtree hash frequencyfreq.set(h,(freq.get(h)||0)+1);// Return subtree hashreturnh;}// Function to count duplicate subtreesfunctioncountDupSubtrees(root){// Hash frequency mapletfreq=newMap();// DFS calldfs(root,freq);letans=0;// Count duplicate subtree hashesfor(letcountoffreq.values()){if(count>1)ans++;}// Return answerreturnans;}// Driver code// Building treeconstroot=newNode(1);root.children.push(newNode(2));root.children.push(newNode(2));root.children.push(newNode(3));root.children[0].children.push(newNode(4));root.children[1].children.push(newNode(4));root.children[1].children.push(newNode(4));root.children[1].children.push(newNode(3));// Function callconsole.log(countDupSubtrees(root));