Count of duplicate Subtrees in an N-ary Tree

Last Updated : 22 Jun, 2026

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.

2056958196

Input: root = [1, N, 2, 3, N, 4, 5, 6, N, N, N, N]
Output: 0
Explanation: No duplicate subtree found.

Try It Yourself
redirect icon

[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>
using namespace std;

// Structure of a tree node
class Node {
public:
    int data;
    vector<Node*> children;
    Node(int val) { data = val; }
};

string dfs(Node* root, unordered_map<string, int>& f)
{
    // Base condition
    if (root == 0)
        return "";
    string s = "(";
    s += to_string(root->data);
    
    // Dfs call for all children
    for (auto child : root->children) {
        s += dfs(child, f);
    }
    s += ')';
    f[s]++;

    // Return answer string
    return s;
}

// Function to count number of duplicate subtrees
int countDupSubtrees(Node* root)
{
    // Declare a map
    unordered_map<string, int> f;

    // DFS call
    dfs(root, f);
    int ans = 0;

    // Loop for traversing the map
    for (auto p : f)
        if (p.second > 1)
            ans++;

    // Return the count of duplicate subtrees
    return ans;
}

// Driver code
int main()
{
    Node* root = new Node(1);
    root->children.push_back(new Node(2));
    root->children.push_back(new Node(2));
    root->children.push_back(new Node(3));
    root->children[0]->children.push_back(new Node(4));
    root->children[1]->children.push_back(new Node(4));
    root->children[1]->children.push_back(new Node(4));
    root->children[1]->children.push_back(new Node(3));
    cout << countDupSubtrees(root);
    return 0;
}
Java
// Java program to count duplicate subtrees in an N-ary tree
import java.util.*;

class Node {
    int data;
    List<Node> children;
    
    Node(int val) {
        data = val;
        children = new ArrayList<>();
    }
}

class GfG {
    
    static String dfs(Node root, Map<String, Integer> freq) {
        // Base condition
        if (root == null)
            return "";
        
        String s = "(" + root.data;
        
        // DFS call for all children
        for (Node child : root.children) {
            s += dfs(child, freq);
        }
        s += ")";
        
        freq.put(s, freq.getOrDefault(s, 0) + 1);
        
        // Return answer string
        return s;
    }
    
    // Function to count number of duplicate subtrees
    static int countDupSubtrees(Node root) {
        // Declare a map
        Map<String, Integer> freq = new HashMap<>();
        
        // DFS call
        dfs(root, freq);
        int ans = 0;
        
        // Loop for traversing the map
        for (int count : freq.values()) {
            if (count > 1)
                ans++;
        }
        
        // Return the count of duplicate subtrees
        return ans;
    }
    
    public static void main(String[] args) {
        Node root = new Node(1);
        root.children.add(new Node(2));
        root.children.add(new Node(2));
        root.children.add(new Node(3));
        root.children.get(0).children.add(new Node(4));
        root.children.get(1).children.add(new Node(4));
        root.children.get(1).children.add(new Node(4));
        root.children.get(1).children.add(new Node(3));
        
        System.out.println(countDupSubtrees(root));
    }
}
Python
# Python program to count duplicate subtrees in an N-ary tree

class Node:
    def __init__(self, key, children=None):
        self.key = key
        self.children = children or []
    
    def __str__(self):
        return str(self.key)

class Solution:
    def dfs(self, root, f):
        # Base condition
        if root is None:
            return ""
        
        s = "(" + str(root.key)
        
        # DFS call for all children
        for child in root.children:
            s += self.dfs(child, f)
        
        s += ")"
        f[s] = f.get(s, 0) + 1
        
        # Return answer string
        return s
    
    def countDupSubtrees(self, root):
        # Declare a dictionary
        f = {}
        
        # DFS call
        self.dfs(root, f)
        ans = 0
        
        # Loop for traversing the dictionary
        for count in f.values():
            if count > 1:
                ans += 1
        
        # Return the count of duplicate subtrees
        return ans

# Driver code
if __name__ == "__main__":
    # Building the tree
    root = 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 tree
using System;
using System.Collections.Generic;

class Node {
    public int data;
    public List<Node> children;
    
    public Node(int val) {
        data = val;
        children = new List<Node>();
    }
}

class GfG {
    
    static string dfs(Node root, Dictionary<string, int> freq) {
        // Base condition
        if (root == null)
            return "";
        
        string s = "(" + root.data;
        
        // DFS call for all children
        foreach (Node child in root.children) {
            s += dfs(child, freq);
        }
        s += ")";
        
        if (freq.ContainsKey(s))
            freq[s]++;
        else
            freq[s] = 1;
        
        // Return answer string
        return s;
    }
    
    // Function to count number of duplicate subtrees
    static int countDupSubtrees(Node root) {
        // Declare a dictionary
        Dictionary<string, int> freq = new Dictionary<string, int>();
        
        // DFS call
        dfs(root, freq);
        int ans = 0;
        
        // Loop for traversing the dictionary
        foreach (int count in freq.Values) {
            if (count > 1)
                ans++;
        }
        
        // Return the count of duplicate subtrees
        return ans;
    }
    
    static void Main(string[] args) {
        Node root = new Node(1);
        root.children.Add(new Node(2));
        root.children.Add(new Node(2));
        root.children.Add(new Node(3));
        root.children[0].children.Add(new Node(4));
        root.children[1].children.Add(new Node(4));
        root.children[1].children.Add(new Node(4));
        root.children[1].children.Add(new Node(3));
        
        Console.WriteLine(countDupSubtrees(root));
    }
}
JavaScript
// JavaScript program to count duplicate subtrees in an N-ary tree

class Node {
    constructor(val) {
        this.data = val;
        this.children = [];
    }
}

function dfs(root, freq) {
    // Base condition
    if (root === null)
        return "";
    
    let s = "(" + root.data;
    
    // DFS call for all children
    for (let child of root.children) {
        s += dfs(child, freq);
    }
    s += ")";
    
    freq.set(s, (freq.get(s) || 0) + 1);
    
    // Return answer string
    return s;
}

// Function to count number of duplicate subtrees
function countDupSubtrees(root) {
    // Declare a map
    let freq = new Map();
    
    // DFS call
    dfs(root, freq);
    let ans = 0;
    
    // Loop for traversing the map
    for (let count of freq.values()) {
        if (count > 1)
            ans++;
    }
    
    // Return the count of duplicate subtrees
    return ans;
}

// Driver code
const root = new Node(1);
root.children.push(new Node(2));
root.children.push(new Node(2));
root.children.push(new Node(3));
root.children[0].children.push(new Node(4));
root.children[1].children.push(new Node(4));
root.children[1].children.push(new Node(4));
root.children[1].children.push(new Node(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>
using namespace std;

// Structure of a tree node
class Node {
public:
    
    int data;
    vector<Node*> children;
    
    Node(int val) {
        data = val;
    }
};

// DFS function for hashing
long long dfs(Node* root,
              unordered_map<long long, int>& f)
{
    // Base condition
    if(root == NULL)
        return 7;

    // Start hash with node value
    long long h = root->data;

    // DFS for all children
    for(auto child : root->children) {

        long long childHash = dfs(child, f);

        // Combine hashes
        h = h * 31 + childHash * 17;
    }

    // Store subtree hash frequency
    f[h]++;

    // Return subtree hash
    return h;
}

// Function to count duplicate subtrees
int countDupSubtrees(Node* root)
{
    // Hash frequency map
    unordered_map<long long, int> f;

    // DFS call
    dfs(root, f);

    int ans = 0;

    // Count duplicate subtree hashes
    for(auto x : f) {

        if(x.second > 1)
            ans++;
    }

    // Return answer
    return ans;
}

// Driver code
int main()
{
    // Building tree
    Node* root = new Node(1);

    root->children.push_back(new Node(2));
    root->children.push_back(new Node(2));
    root->children.push_back(new Node(3));

    root->children[0]->children.push_back(new Node(4));

    root->children[1]->children.push_back(new Node(4));
    root->children[1]->children.push_back(new Node(4));
    root->children[1]->children.push_back(new Node(3));

    // Function call
    cout << countDupSubtrees(root);

    return 0;
}
Java
// Java program to count duplicate subtrees in an N-ary tree using hashing
import java.util.*;

class Node {
    int data;
    List<Node> children;
    
    Node(int val) {
        data = val;
        children = new ArrayList<>();
    }
}

class GfG {
    
    // DFS function for hashing
    static long dfs(Node root, Map<Long, Integer> freq) {
        // Base condition
        if (root == null)
            return 7;
        
        // Start hash with node value
        long h = root.data;
        
        // DFS for all children
        for (Node child : root.children) {
            long childHash = dfs(child, freq);
            // Combine hashes
            h = h * 31 + childHash * 17;
        }
        
        // Store subtree hash frequency
        freq.put(h, freq.getOrDefault(h, 0) + 1);
        
        // Return subtree hash
        return h;
    }
    
    // Function to count duplicate subtrees
    static int countDupSubtrees(Node root) {
        // Hash frequency map
        Map<Long, Integer> freq = new HashMap<>();
        
        // DFS call
        dfs(root, freq);
        
        int ans = 0;
        
        // Count duplicate subtree hashes
        for (int count : freq.values()) {
            if (count > 1)
                ans++;
        }
        
        // Return answer
        return ans;
    }
    
    public static void main(String[] args) {
        // Building tree
        Node root = new Node(1);
        
        root.children.add(new Node(2));
        root.children.add(new Node(2));
        root.children.add(new Node(3));
        
        root.children.get(0).children.add(new Node(4));
        
        root.children.get(1).children.add(new Node(4));
        root.children.get(1).children.add(new Node(4));
        root.children.get(1).children.add(new Node(3));
        
        // Function call
        System.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 '''
class Node:
    def __init__(self, key, children=None):
        self.key = key
        self.children = children or []
    
    def __str__(self):
        return str(self.key)

class Solution:
    # DFS function for hashing
    def dfs(self, root, freq):
        # Base condition
        if root is None:
            return 7
        
        # Start hash with node key
        h = root.key
        
        # DFS for all children
        for child in root.children:
            childHash = self.dfs(child, freq)
            # Combine hashes
            h = h * 31 + childHash * 17
        
        # Store subtree hash frequency
        freq[h] = freq.get(h, 0) + 1
        
        # Return subtree hash
        return h
    
    # Function to count duplicate subtrees
    def countDupSubtrees(self, root):
        # Hash frequency map
        freq = {}
        
        # DFS call
        self.dfs(root, freq)
        
        ans = 0
        
        # Count duplicate subtree hashes
        for count in freq.values():
            if count > 1:
                ans += 1
        
        # Return answer
        return ans

# Driver code
if __name__ == "__main__":
    # Building tree
    root = Node(1)
    
    # Adding children to root
    node2_1 = Node(2)
    node2_2 = Node(2)
    node3 = Node(3)
    
    root.children = [node2_1, node2_2, node3]
    
    # Adding children to first node2
    node2_1.children = [Node(4)]
    
    # Adding children to second node2
    node2_2.children = [Node(4), Node(4), Node(3)]
    
    # Creating Solution object and calling function
    sol = Solution()
    print(sol.countDupSubtrees(root))
C#
// C# program to count duplicate subtrees in an N-ary tree using hashing
using System;
using System.Collections.Generic;

class Node {
    public int data;
    public List<Node> children;
    
    public Node(int val) {
        data = val;
        children = new List<Node>();
    }
}

class GfG {
    
    // DFS function for hashing
    static long dfs(Node root, Dictionary<long, int> freq) {
        // Base condition
        if (root == null)
            return 7;
        
        // Start hash with node value
        long h = root.data;
        
        // DFS for all children
        foreach (Node child in root.children) {
            long childHash = dfs(child, freq);
            // Combine hashes
            h = h * 31 + childHash * 17;
        }
        
        // Store subtree hash frequency
        if (freq.ContainsKey(h))
            freq[h]++;
        else
            freq[h] = 1;
        
        // Return subtree hash
        return h;
    }
    
    // Function to count duplicate subtrees
    static int countDupSubtrees(Node root) {
        // Hash frequency map
        Dictionary<long, int> freq = new Dictionary<long, int>();
        
        // DFS call
        dfs(root, freq);
        
        int ans = 0;
        
        // Count duplicate subtree hashes
        foreach (int count in freq.Values) {
            if (count > 1)
                ans++;
        }
        
        // Return answer
        return ans;
    }
    
    static void Main(string[] args) {
        // Building tree
        Node root = new Node(1);
        
        root.children.Add(new Node(2));
        root.children.Add(new Node(2));
        root.children.Add(new Node(3));
        
        root.children[0].children.Add(new Node(4));
        
        root.children[1].children.Add(new Node(4));
        root.children[1].children.Add(new Node(4));
        root.children[1].children.Add(new Node(3));
        
        // Function call
        Console.WriteLine(countDupSubtrees(root));
    }
}
JavaScript
// JavaScript program to count duplicate subtrees in an N-ary tree using hashing

class Node {
    constructor(val) {
        this.data = val;
        this.children = [];
    }
}

// DFS function for hashing
function dfs(root, freq) {
    // Base condition
    if (root === null)
        return 7;
    
    // Start hash with node value
    let h = root.data;
    
    // DFS for all children
    for (let child of root.children) {
        let childHash = dfs(child, freq);
        // Combine hashes
        h = h * 31 + childHash * 17;
    }
    
    // Store subtree hash frequency
    freq.set(h, (freq.get(h) || 0) + 1);
    
    // Return subtree hash
    return h;
}

// Function to count duplicate subtrees
function countDupSubtrees(root) {
    // Hash frequency map
    let freq = new Map();
    
    // DFS call
    dfs(root, freq);
    
    let ans = 0;
    
    // Count duplicate subtree hashes
    for (let count of freq.values()) {
        if (count > 1)
            ans++;
    }
    
    // Return answer
    return ans;
}

// Driver code
// Building tree
const root = new Node(1);

root.children.push(new Node(2));
root.children.push(new Node(2));
root.children.push(new Node(3));

root.children[0].children.push(new Node(4));

root.children[1].children.push(new Node(4));
root.children[1].children.push(new Node(4));
root.children[1].children.push(new Node(3));

// Function call
console.log(countDupSubtrees(root));

Output
2


Comment