Isomorphism in N-ary Trees
Given two N-ary trees having M nodes each. Also, given their edges and their roots respectively. The task is to check if they are isomorphic trees or not. If both the trees are isomorphic then print “Yes” else print “No”.
Examples:
Input: M = 9, Root Node of tree-1: 1, Root Node of tree-2: 3
Edges of Tree-1: { (1, 3), (3, 4), (3, 5), (1, 8), (8, 9), (1, 2), (2, 6), (2, 7) }
Edges of Tree-2: { (3, 1), (1, 2), (1, 5), (3, 6), (6, 7), (3, 4), (4, 8), (4, 9) }
Output: YES
Input: M = 9, Root Node of tree-1: 6, Root Node of tree-2: 7
Edges of Tree-1: {(1, 3),(1, 2), (1, 8), (3, 4), (3, 5), (8, 9), (2, 6), (2, 7)}
Edges of Tree-2: {(1, 2), (1, 5), (3, 1), (3, 4), (4, 8), (4, 9), (6, 3), (7, 6)}
Output: NO
Approach:
The idea is to find out the canonical form of both the trees and comparing them. The leaf node will return “()” to its subsequent upper levels.
Below is the example showing the process of finding the canonical form.
Below is the implementation of the above approach:
CPP
#include <bits/stdc++.h>
using namespace std;
map< int , vector< int > > tree;
string ConvertCanonical( int vertex,
int parent)
{
vector<string> child;
for ( auto neighbour : tree[vertex]) {
if (neighbour == parent)
continue ;
child.push_back(ConvertCanonical(
neighbour, vertex));
}
string str = "(" ;
sort(child.begin(), child.end());
for ( auto j : child)
str += j;
str += ")" ;
return str;
}
void addedge( int a, int b)
{
tree[a].push_back(b);
tree[b].push_back(a);
}
int main()
{
addedge(1, 3);
addedge(1, 2);
addedge(1, 5);
addedge(3, 4);
addedge(4, 8);
addedge(4, 9);
addedge(3, 6);
addedge(6, 7);
string tree1 = ConvertCanonical(3, -1);
tree.clear();
addedge(1, 3);
addedge(3, 4);
addedge(3, 5);
addedge(1, 8);
addedge(8, 9);
addedge(1, 2);
addedge(2, 6);
addedge(2, 7);
string tree2 = ConvertCanonical(1, -1);
if (tree1 == tree2)
cout << "YES" << endl;
else
cout << "NO" << endl;
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
static Map<Integer, List<Integer> > tree
= new HashMap<>();
static String ConvertCanonical( int vertex, int parent)
{
List<String> child = new ArrayList<>();
for ( int neighbour :
tree.getOrDefault(vertex, new ArrayList<>())) {
if (neighbour == parent) {
continue ;
}
child.add(ConvertCanonical(neighbour, vertex));
}
String str = "(" ;
Collections.sort(child);
for (String j : child) {
str += j;
}
str += ")" ;
return str;
}
static void addEdge( int a, int b)
{
if (!tree.containsKey(a)) {
tree.put(a, new ArrayList<>());
}
tree.get(a).add(b);
if (!tree.containsKey(b)) {
tree.put(b, new ArrayList<>());
}
tree.get(b).add(a);
}
public static void main(String[] args)
{
addEdge( 1 , 3 );
addEdge( 1 , 2 );
addEdge( 1 , 5 );
addEdge( 3 , 4 );
addEdge( 4 , 8 );
addEdge( 4 , 9 );
addEdge( 3 , 6 );
addEdge( 6 , 7 );
String tree1 = ConvertCanonical( 3 , - 1 );
tree.clear();
addEdge( 1 , 3 );
addEdge( 3 , 4 );
addEdge( 3 , 5 );
addEdge( 1 , 8 );
addEdge( 8 , 9 );
addEdge( 1 , 2 );
addEdge( 2 , 6 );
addEdge( 2 , 7 );
String tree2 = ConvertCanonical( 1 , - 1 );
if (tree1.equals(tree2)) {
System.out.println( "YES" );
}
else {
System.out.println( "NO" );
}
}
}
|
Python3
tree = dict ()
def ConvertCanonical(vertex, parent):
child = []
for neighbour in tree[vertex] :
if (neighbour = = parent):
continue
child.append(ConvertCanonical(
neighbour, vertex))
s = "("
child.sort()
for j in child:
s + = j
s + = ")"
return s
def addedge(a, b):
if a in tree:
tree[a].append(b)
else :
tree[a] = [b,]
if b in tree:
tree[b].append(a)
else :
tree[b] = [a,]
if __name__ = = '__main__' :
addedge( 1 , 3 )
addedge( 1 , 2 )
addedge( 1 , 5 )
addedge( 3 , 4 )
addedge( 4 , 8 )
addedge( 4 , 9 )
addedge( 3 , 6 )
addedge( 6 , 7 )
tree1 = ConvertCanonical( 3 , - 1 )
tree.clear()
addedge( 1 , 3 )
addedge( 3 , 4 )
addedge( 3 , 5 )
addedge( 1 , 8 )
addedge( 8 , 9 )
addedge( 1 , 2 )
addedge( 2 , 6 )
addedge( 2 , 7 )
tree2 = ConvertCanonical( 1 , - 1 )
if (tree1 = = tree2):
print ( "YES" )
else :
print ( "NO" )
|
C#
using System;
using System.Collections.Generic;
public class GFG {
static Dictionary< int , List< int > > tree
= new Dictionary< int , List< int > >();
static string ConvertCanonical( int vertex, int parent)
{
List< string > child = new List< string >();
if (tree.ContainsKey(vertex)) {
foreach ( int neighbour in tree[vertex])
{
if (neighbour == parent) {
continue ;
}
child.Add(
ConvertCanonical(neighbour, vertex));
}
}
string str = "(" ;
child.Sort();
foreach ( string j in child) { str += j; }
str += ")" ;
return str;
}
static void addEdge( int a, int b)
{
if (!tree.ContainsKey(a)) {
tree.Add(a, new List< int >());
}
tree[a].Add(b);
if (!tree.ContainsKey(b)) {
tree.Add(b, new List< int >());
}
tree[b].Add(a);
}
static public void Main()
{
addEdge(1, 3);
addEdge(1, 2);
addEdge(1, 5);
addEdge(3, 4);
addEdge(4, 8);
addEdge(4, 9);
addEdge(3, 6);
addEdge(6, 7);
string tree1 = ConvertCanonical(3, -1);
tree.Clear();
addEdge(1, 3);
addEdge(3, 4);
addEdge(3, 5);
addEdge(1, 8);
addEdge(8, 9);
addEdge(1, 2);
addEdge(2, 6);
addEdge(2, 7);
String tree2 = ConvertCanonical(1, -1);
if (tree1.Equals(tree2)) {
Console.WriteLine( "YES" );
}
else {
Console.WriteLine( "NO" );
}
}
}
|
Javascript
<script>
function addedge(a, b) {
if (!tree[a])
tree[a] = []
if (!tree[b])
tree[b] = []
tree[a].push(b);
tree[b].push(a);
}
function ConvertCanonical(vertex, parent) {
let child = [];
for (let neighbour of tree[vertex]) {
if (neighbour === parent) continue ;
child.push(ConvertCanonical(neighbour, vertex));
}
let str = "(" ;
child.sort();
for (let j of child) str += j;
str += ")" ;
return str;
}
let tree = {};
addedge(1, 3);
addedge(1, 2);
addedge(1, 5);
addedge(3, 4);
addedge(4, 8);
addedge(4, 9);
addedge(3, 6);
addedge(6, 7);
let tree1 = ConvertCanonical(3, -1);
tree = {};
addedge(1, 3);
addedge(3, 4);
addedge(3, 5);
addedge(1, 8);
addedge(8, 9);
addedge(1, 2);
addedge(2, 6);
addedge(2, 7);
let tree2 = ConvertCanonical(1, -1);
if (tree1 === tree2) {
console.log( "YES" );
} else {
console.log( "NO" );
}
|
Time complexity: O(N log N), where N is the number of vertices in the tree. This is because for each vertex, we perform a sorting operation on its child vector, which takes O(log N) time in the worst case. Since there are N vertices in the tree, the overall time complexity is O(N log N).
Auxiliary space: O(N), where N is the number of vertices in the tree. This is because we use a map to represent the tree, which takes O(N) space to store all the vertices and their corresponding neighbors. Additionally, during the recursive calls of the ConvertCanonical function, we create a vector of strings to store the canonical form of each vertex and its subtree, which can take up to O(N) space in the worst case.
Last Updated :
06 Jun, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...