Given a Binary Tree, check whether the Binary tree contains a duplicate sub-tree of size 2 or more.
Note: Two same leaf nodes are not considered as the subtree size of a leaf node is one.
Input : Binary Tree
A
/ \
B C
/ \ \
D E B
/ \
D E
Output : Yes
Asked in : Google Interview

Tree with duplicate Sub-Tree [ highlight by blue color ellipse ]
[ Method 1]
A simple solution is that, we pick every node of tree and try to find is any sub-tree of given tree is present in tree which is identical with that sub-tree. Here we can use below post to find if a subtree is present anywhere else in tree.
Check if a binary tree is subtree of another binary tree
[Method 2 ]( Efficient solution )
An Efficient solution based on tree serialization and hashing. The idea is to serialize subtrees as strings and store the strings in hash table. Once we find a serialized tree (which is not a leaf) already existing in hash-table, we return true.
Below The implementation of above idea.
C++
#include<bits/stdc++.h>
using namespace std;
const char MARKER = '$' ;
struct Node
{
char key;
Node *left, *right;
};
Node* newNode( char key)
{
Node* node = new Node;
node->key = key;
node->left = node->right = NULL;
return node;
}
unordered_set<string> subtrees;
string dupSubUtil(Node *root)
{
string s = "" ;
if (root == NULL)
return s + MARKER;
string lStr = dupSubUtil(root->left);
if (lStr.compare(s) == 0)
return s;
string rStr = dupSubUtil(root->right);
if (rStr.compare(s) == 0)
return s;
s = s + root->key + lStr + rStr;
if (s.length() > 3 &&
subtrees.find(s) != subtrees.end())
return "" ;
subtrees.insert(s);
return s;
}
int main()
{
Node *root = newNode( 'A' );
root->left = newNode( 'B' );
root->right = newNode( 'C' );
root->left->left = newNode( 'D' );
root->left->right = newNode( 'E' );
root->right->right = newNode( 'B' );
root->right->right->right = newNode( 'E' );
root->right->right->left= newNode( 'D' );
string str = dupSubUtil(root);
(str.compare( "" ) == 0) ? cout << " Yes " :
cout << " No " ;
return 0;
}
|
Java
import java.util.HashSet;
public class Main {
static char MARKER = '$' ;
public static String dupSubUtil(Node root, HashSet<String> subtrees)
{
String s = "" ;
if (root == null )
return s + MARKER;
String lStr = dupSubUtil(root.left,subtrees);
if (lStr.equals(s))
return s;
String rStr = dupSubUtil(root.right,subtrees);
if (rStr.equals(s))
return s;
s = s + root.data + "%" + lStr+ "%" + rStr;
if (s.length() > 7 && subtrees.contains(s))
return "" ;
subtrees.add(s);
return s;
}
public static String dupSub(Node root)
{
HashSet<String> subtrees= new HashSet<>();
return dupSubUtil(root,subtrees);
}
public static void main(String args[])
{
Node root = new Node( 'A' );
root.left = new Node( 'B' );
root.right = new Node( 'C' );
root.left.left = new Node( 'D' );
root.left.right = new Node( 'E' );
root.right.right = new Node( 'B' );
root.right.right.right = new Node( 'E' );
root.right.right.left= new Node( 'D' );
String str = dupSub(root);
if (str.equals( "" ))
System.out.print( " Yes " );
else
System.out.print( " No " );
}
}
class Node {
int data;
Node left,right;
Node( int data)
{
this .data=data;
}
};
|
Python3
MARKER = '$'
class Node:
def __init__( self , x):
self .key = x
self .left = None
self .right = None
subtrees = {}
def dupSubUtil(root):
global subtrees
s = ""
if (root = = None ):
return s + MARKER
lStr = dupSubUtil(root.left)
if (s in lStr):
return s
rStr = dupSubUtil(root.right)
if (s in rStr):
return s
s = s + root.key + lStr + rStr
if ( len (s) > 3 and s in subtrees):
return ""
subtrees[s] = 1
return s
if __name__ = = '__main__' :
root = Node( 'A' )
root.left = Node( 'B' )
root.right = Node( 'C' )
root.left.left = Node( 'D' )
root.left.right = Node( 'E' )
root.right.right = Node( 'B' )
root.right.right.right = Node( 'E' )
root.right.right.left = Node( 'D' )
str = dupSubUtil(root)
if "" in str :
print ( " Yes " )
else :
print ( " No " )
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static char MARKER = '$' ;
public static String dupSubUtil(Node root,
HashSet<String> subtrees)
{
String s = "" ;
if (root == null )
return s + MARKER;
String lStr = dupSubUtil(root.left,subtrees);
if (lStr.Equals(s))
return s;
String rStr = dupSubUtil(root.right,subtrees);
if (rStr.Equals(s))
return s;
s = s + root.data + lStr + rStr;
if (s.Length > 3 && subtrees.Contains(s))
return "" ;
subtrees.Add(s);
return s;
}
public static String dupSub(Node root)
{
HashSet<String> subtrees = new HashSet<String>();
return dupSubUtil(root,subtrees);
}
public static void Main(String []args)
{
Node root = new Node( 'A' );
root.left = new Node( 'B' );
root.right = new Node( 'C' );
root.left.left = new Node( 'D' );
root.left.right = new Node( 'E' );
root.right.right = new Node( 'B' );
root.right.right.right = new Node( 'E' );
root.right.right.left= new Node( 'D' );
String str = dupSub(root);
if (str.Equals( "" ))
Console.Write( " Yes " );
else
Console.Write( " No " );
}
}
public class Node
{
public int data;
public Node left,right;
public Node( int data)
{
this .data = data;
}
};
|
Javascript
<script>
let MARKER = '$' ;
class Node {
constructor(data)
{
this .data=data;
}
}
function dupSubUtil(root,subtrees)
{
let s = "" ;
if (root == null )
return s + MARKER;
let lStr = dupSubUtil(root.left,subtrees);
if (lStr==(s))
return s;
let rStr = dupSubUtil(root.right,subtrees);
if (rStr==(s))
return s;
s = s + root.data + lStr + rStr;
if (s.length > 3 && subtrees.has(s))
return "" ;
subtrees.add(s);
return s;
}
function dupSub(root)
{
let subtrees= new Set();
return dupSubUtil(root,subtrees);
}
let root = new Node( 'A' );
root.left = new Node( 'B' );
root.right = new Node( 'C' );
root.left.left = new Node( 'D' );
root.left.right = new Node( 'E' );
root.right.right = new Node( 'B' );
root.right.right.right = new Node( 'E' );
root.right.right.left= new Node( 'D' );
let str = dupSub(root);
if (str==( "" ))
document.write( " Yes " );
else
document.write( " No " );
</script>
|
Time Complexity: O(n)
Auxiliary Space: O(n)
The time complexity of the above program is O(n) where n is the number of nodes in the given binary tree. We are using hashing to store the subtrees which take O(n) space for all the subtrees.
If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!