Open In App

Check if all levels of two trees are anagrams or not

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Given two binary trees, we have to check if each of their levels is an anagram of the other or not. 
Example: 


 

Tree 1:
Level 0 : 1
Level 1 : 3, 2
Level 2 : 5, 4
Tree 2:
Level 0 : 1
Level 1 : 2, 3
Level 2 : 4, 5



As we can clearly see all the levels of above two binary trees are anagrams of each other, hence return true.

Naive Approach: Below is the step-by-step explanation of the naive approach to do this: 

  1. Write a recursive program for level order traversal of a tree.
  2. Traverse each level of both the trees one by one and store the result of traversals in 2 different vectors, one for each tree.
  3. Sort both the vectors and compare them iteratively for each level, if they are the same for each level then return true else return false.

Code:

C++




/* Iterative program to check if two trees are level
  by level anagram. */
#include <bits/stdc++.h>
using namespace std;
 
// A Binary Tree Node
struct Node {
    struct Node *left, *right;
    int data;
};
 
// function to get nodes at each level
void EachLevel(Node* root,
               unordered_map<int, vector<int> >& mm,
               int level)
{
    // base case
    if (!root)
        return;
 
    // adding node to its level
    mm[level].push_back(root->data);
 
    // increasing level
    level++;
 
    // moving left
    EachLevel(root->left, mm, level);
 
    // moving right
    EachLevel(root->right, mm, level);
}
 
// Returns true if trees with root1 and root2
// are level by level anagram, else returns false.
bool areAnagrams(unordered_map<int, vector<int> > mm1,
                 unordered_map<int, vector<int> > mm2)
{
    // map to help in checking anagram
    unordered_map<int, int> temp;
 
    // iterating each level of tree1
    for (auto x : mm1) {
        // storing node for current level
        for (auto y : x.second) {
            temp[y]++;
        }
 
        // checking if tree1 have node same as tree2
        // level or not
        for (auto y : mm2[x.first]) {
            if (!temp[y])
                return false;
            temp[y]--;
        }
    }
 
    // clearing map to check level of
    // tree2 as like tree1
    temp.clear();
 
    // iterating over tree2 levels
    for (auto x : mm2) {
        // storing each level nodes
        for (auto y : x.second) {
            temp[y]++;
        }
 
        // checking if tree2 have nodes at current
        // level as tree1
        for (auto y : mm1[x.first]) {
            if (!temp[y])
                return false;
            temp[y]--;
        }
    }
 
    return true;
}
 
// Utility function to create a new tree Node
Node* newNode(int data)
{
    Node* temp = new Node;
    temp->data = data;
    temp->left = temp->right = NULL;
    return temp;
}
 
// Driver program to test above functions
int main()
{
    // Constructing both the trees.
    struct Node* root1 = newNode(1);
    root1->left = newNode(3);
    root1->right = newNode(2);
    root1->right->left = newNode(5);
    root1->right->right = newNode(4);
 
    struct Node* root2 = newNode(1);
    root2->left = newNode(2);
    root2->right = newNode(3);
    root2->left->left = newNode(4);
    root2->left->right = newNode(5);
 
    // maps for both trees
    unordered_map<int, vector<int> > mm1, mm2;
 
    EachLevel(root1, mm1, 0);
    EachLevel(root2, mm2, 0);
 
    if (areAnagrams(mm1, mm2))
        cout << "Yes";
    else
        cout << "No";
 
    return 0;
}
 
// This code is contributed by shubhamrajput6156.


Java




//Java code for the above apporach:
import java.util.*;
 
// A Binary Tree Node
class Node {
    Node left, right;
    int data;
 
    Node(int data) {
        this.data = data;
        left = right = null;
    }
}
 
public class Main {
    // function to get nodes at each level
    static void EachLevel(Node root, HashMap<Integer, ArrayList<Integer>> mm, int level) {
        // base case
        if (root == null)
            return;
 
        // adding node to its level
        if (!mm.containsKey(level)) {
            mm.put(level, new ArrayList<>());
        }
        mm.get(level).add(root.data);
 
        // increasing level
        level++;
 
        // moving left
        EachLevel(root.left, mm, level);
 
        // moving right
        EachLevel(root.right, mm, level);
    }
 
    // Returns true if trees with root1 and root2
    // are level by level anagram, else returns false.
    static boolean areAnagrams(HashMap<Integer, ArrayList<Integer>> mm1, HashMap<Integer, ArrayList<Integer>> mm2) {
        // map to help in checking anagram
        HashMap<Integer, Integer> temp = new HashMap<>();
 
        // iterating each level of tree1
        for (Map.Entry<Integer, ArrayList<Integer>> entry : mm1.entrySet()) {
            // storing node for current level
            for (int y : entry.getValue()) {
                temp.put(y, temp.getOrDefault(y, 0) + 1);
            }
 
            // checking if tree1 has nodes same as tree2
            // level or not
            for (int y : mm2.get(entry.getKey())) {
                if (temp.getOrDefault(y, 0) == 0)
                    return false;
                temp.put(y, temp.get(y) - 1);
            }
        }
 
        // clearing map to check level of
        // tree2 as like tree1
        temp.clear();
 
        // iterating over tree2 levels
        for (Map.Entry<Integer, ArrayList<Integer>> entry : mm2.entrySet()) {
            // storing each level nodes
            for (int y : entry.getValue()) {
                temp.put(y, temp.getOrDefault(y, 0) + 1);
            }
 
            // checking if tree2 has nodes at current
            // level as tree1
            for (int y : mm1.get(entry.getKey())) {
                if (temp.getOrDefault(y, 0) == 0)
                    return false;
                temp.put(y, temp.get(y) - 1);
            }
        }
 
        return true;
    }
 
    // Utility function to create a new tree Node
    static Node newNode(int data) {
        return new Node(data);
    }
 
    // Driver program to test above functions
    public static void main(String[] args) {
        // Constructing both the trees.
        Node root1 = newNode(1);
        root1.left = newNode(3);
        root1.right = newNode(2);
        root1.right.left = newNode(5);
        root1.right.right = newNode(4);
 
        Node root2 = newNode(1);
        root2.left = newNode(2);
        root2.right = newNode(3);
        root2.left.left = newNode(4);
        root2.left.right = newNode(5);
 
        // maps for both trees
        HashMap<Integer, ArrayList<Integer>> mm1 = new HashMap<>();
        HashMap<Integer, ArrayList<Integer>> mm2 = new HashMap<>();
 
        EachLevel(root1, mm1, 0);
        EachLevel(root2, mm2, 0);
 
        if (areAnagrams(mm1, mm2))
            System.out.println("Yes");
        else
            System.out.println("No");
    }
}
 
// this code is contributed by uttamdp_10


Python3




from collections import defaultdict
 
# A Binary Tree Node
class Node:
    def __init__(self, data):
        self.data = data
        self.left = self.right = None
 
# function to get nodes at each level
def EachLevel(root, mm, level):
    # base case
    if not root:
        return
 
    # adding node to its level
    mm[level].append(root.data)
 
    # increasing level
    level += 1
 
    # moving left
    EachLevel(root.left, mm, level)
 
    # moving right
    EachLevel(root.right, mm, level)
 
# Returns true if trees with root1 and root2
# are level by level anagram, else returns false.
def areAnagrams(mm1, mm2):
    # map to help in checking anagram
    temp = defaultdict(int)
 
    # iterating each level of tree1
    for x in mm1:
        # storing node for current level
        for y in mm1[x]:
            temp[y] += 1
 
        # checking if tree1 has a node the same as tree2 at this level or not
        for y in mm2[x]:
            if not temp[y]:
                return False
            temp[y] -= 1
 
    # clearing map to check level of tree2 as like tree1
    temp.clear()
 
    # iterating over tree2 levels
    for x in mm2:
        # storing each level nodes
        for y in mm2[x]:
            temp[y] += 1
 
        # checking if tree2 has nodes at the current level as tree1
        for y in mm1[x]:
            if not temp[y]:
                return False
            temp[y] -= 1
 
    return True
 
# Utility function to create a new tree Node
def newNode(data):
    temp = Node(data)
    return temp
 
# Driver program to test above functions
if __name__ == "__main__":
    # Constructing both trees.
    root1 = newNode(1)
    root1.left = newNode(3)
    root1.right = newNode(2)
    root1.right.left = newNode(5)
    root1.right.right = newNode(4)
 
    root2 = newNode(1)
    root2.left = newNode(2)
    root2.right = newNode(3)
    root2.left.left = newNode(4)
    root2.left.right = newNode(5)
 
    # dictionaries for both trees
    mm1, mm2 = defaultdict(list), defaultdict(list)
 
    EachLevel(root1, mm1, 0)
    EachLevel(root2, mm2, 0)
 
    if areAnagrams(mm1, mm2):
        print("Yes")
    else:
        print("No")


C#




using System;
using System.Collections.Generic;
 
// A Binary Tree Node
public class Node
{
    public Node left, right;
    public int data;
 
    public Node(int item)
    {
        data = item;
        left = right = null;
    }
}
 
class BinaryTreeAnagramCheck
{
    // Function to get nodes at each level
    static void EachLevel(Node root, Dictionary<int, List<int>> mm, int level)
    {
        // Base case
        if (root == null)
            return;
 
        // Adding node to its level
        if (!mm.ContainsKey(level))
        {
            mm[level] = new List<int>();
        }
        mm[level].Add(root.data);
 
        // Increasing level
        level++;
 
        // Moving left
        EachLevel(root.left, mm, level);
 
        // Moving right
        EachLevel(root.right, mm, level);
    }
 
    // Returns true if trees with root1 and root2
    // are level by level anagram, else returns false.
    static bool AreAnagrams(Dictionary<int, List<int>> mm1, Dictionary<int, List<int>> mm2)
    {
        // Map to help in checking anagram
        Dictionary<int, int> temp = new Dictionary<int, int>();
 
        // Iterating each level of tree1
        foreach (var x in mm1)
        {
            // Storing node for the current level
            foreach (var y in x.Value)
            {
                if (!temp.ContainsKey(y))
                {
                    temp[y] = 0;
                }
                temp[y]++;
            }
 
            // Checking if tree1 has nodes same as tree2
            // level or not
            foreach (var y in mm2[x.Key])
            {
                if (!temp.ContainsKey(y) || temp[y] == 0)
                    return false;
                temp[y]--;
            }
        }
 
        // Clearing map to check the level of
        // tree2 as like tree1
        temp.Clear();
 
        // Iterating over tree2 levels
        foreach (var x in mm2)
        {
            // Storing each level nodes
            foreach (var y in x.Value)
            {
                if (!temp.ContainsKey(y))
                {
                    temp[y] = 0;
                }
                temp[y]++;
            }
 
            // Checking if tree2 has nodes at the current
            // level as tree1
            foreach (var y in mm1[x.Key])
            {
                if (!temp.ContainsKey(y) || temp[y] == 0)
                    return false;
                temp[y]--;
            }
        }
 
        return true;
    }
 
    // Utility function to create a new tree Node
    static Node NewNode(int data)
    {
        return new Node(data);
    }
 
    // Driver program to test above functions
    static void Main()
    {
        // Constructing both the trees.
        Node root1 = NewNode(1);
        root1.left = NewNode(3);
        root1.right = NewNode(2);
        root1.right.left = NewNode(5);
        root1.right.right = NewNode(4);
 
        Node root2 = NewNode(1);
        root2.left = NewNode(2);
        root2.right = NewNode(3);
        root2.left.left = NewNode(4);
        root2.left.right = NewNode(5);
 
        // Maps for both trees
        Dictionary<int, List<int>> mm1 = new Dictionary<int, List<int>>();
        Dictionary<int, List<int>> mm2 = new Dictionary<int, List<int>>();
 
        EachLevel(root1, mm1, 0);
        EachLevel(root2, mm2, 0);
 
        if (AreAnagrams(mm1, mm2))
            Console.WriteLine("Yes");
        else
            Console.WriteLine("No");
    }
}


Javascript




// A Binary Tree Node
class Node {
    constructor(data) {
        this.data = data;
        this.left = null;
        this.right = null;
    }
}
 
// Function to get nodes at each level
function eachLevel(root, mm, level) {
    // Base case
    if (root === null)
        return;
 
    // Adding node to its level
    if (!mm.has(level)) {
        mm.set(level, []);
    }
    mm.get(level).push(root.data);
 
    // Increasing level
    level++;
 
    // Moving left
    eachLevel(root.left, mm, level);
 
    // Moving right
    eachLevel(root.right, mm, level);
}
 
// Function to check if trees with root1 and root2 are level by level anagram
function areAnagrams(mm1, mm2) {
    // Map to help in checking anagram
    let temp = new Map();
 
    // Iterating each level of tree1
    for (let [key, value] of mm1) {
        // Storing node for the current level
        for (let y of value) {
            temp.set(y, (temp.get(y) || 0) + 1);
        }
 
        // Checking if tree1 has nodes same as tree2 level or not
        for (let y of mm2.get(key)) {
            if (!(temp.get(y) || 0))
                return false;
            temp.set(y, temp.get(y) - 1);
        }
    }
 
    // Clearing map to check the level of tree2 as like tree1
    temp.clear();
 
    // Iterating over tree2 levels
    for (let [key, value] of mm2) {
        // Storing each level nodes
        for (let y of value) {
            temp.set(y, (temp.get(y) || 0) + 1);
        }
 
        // Checking if tree2 has nodes at the current level as tree1
        for (let y of mm1.get(key)) {
            if (!(temp.get(y) || 0))
                return false;
            temp.set(y, temp.get(y) - 1);
        }
    }
 
    return true;
}
 
// Utility function to create a new tree Node
function newNode(data) {
    return new Node(data);
}
 
// Driver program to test above functions
function main() {
    // Constructing both the trees.
    let root1 = newNode(1);
    root1.left = newNode(3);
    root1.right = newNode(2);
    root1.right.left = newNode(5);
    root1.right.right = newNode(4);
 
    let root2 = newNode(1);
    root2.left = newNode(2);
    root2.right = newNode(3);
    root2.left.left = newNode(4);
    root2.left.right = newNode(5);
 
    // Maps for both trees
    let mm1 = new Map();
    let mm2 = new Map();
 
    eachLevel(root1, mm1, 0);
    eachLevel(root2, mm2, 0);
 
    if (areAnagrams(mm1, mm2))
        console.log("Yes");
    else
        console.log("No");
}
 
// Invoke the main function
main();


Output

Yes







Time Complexity:- O(N2)
Space Complexity:- O(N)

Efficient Approach: 
The idea is based on below article. 
Print level order traversal line by line | Set 1 
We traverse both trees simultaneously level by level. We store each level both trees in vectors (or array). To check if two vectors are anagram or not, we sort both and then compare.

The extra space is used to store the elements in the queue and vectors.

C++




/* Iterative program to check if two trees are level
   by level anagram. */
#include <bits/stdc++.h>
using namespace std;
 
// A Binary Tree Node
struct Node {
    struct Node *left, *right;
    int data;
};
 
// Returns true if trees with root1 and root2
// are level by level anagram, else returns false.
bool areAnagrams(Node* root1, Node* root2)
{
    // Base Cases
    if (root1 == NULL && root2 == NULL)
        return true;
    if (root1 == NULL || root2 == NULL)
        return false;
 
    // start level order traversal of two trees
    // using two queues.
    queue<Node*> q1, q2;
    q1.push(root1);
    q2.push(root2);
 
    while (1) {
        // n1 (queue size) indicates number of Nodes
        // at current level in first tree and n2 indicates
        // number of nodes in current level of second tree.
        int n1 = q1.size(), n2 = q2.size();
 
        // If n1 and n2 are different
        if (n1 != n2)
            return false;
 
        // If level order traversal is over
        if (n1 == 0)
            break;
 
        // Dequeue all Nodes of current level and
        // Enqueue all Nodes of next level
        vector<int> curr_level1, curr_level2;
        while (n1 > 0) {
            Node* node1 = q1.front();
            q1.pop();
            if (node1->left != NULL)
                q1.push(node1->left);
            if (node1->right != NULL)
                q1.push(node1->right);
            n1--;
 
            Node* node2 = q2.front();
            q2.pop();
            if (node2->left != NULL)
                q2.push(node2->left);
            if (node2->right != NULL)
                q2.push(node2->right);
 
            curr_level1.push_back(node1->data);
            curr_level2.push_back(node2->data);
        }
 
        // Check if nodes of current levels are
        // anagrams or not.
        sort(curr_level1.begin(), curr_level1.end());
        sort(curr_level2.begin(), curr_level2.end());
        if (curr_level1 != curr_level2)
            return false;
    }
 
    return true;
}
 
// Utility function to create a new tree Node
Node* newNode(int data)
{
    Node* temp = new Node;
    temp->data = data;
    temp->left = temp->right = NULL;
    return temp;
}
 
// Driver program to test above functions
int main()
{
    // Constructing both the trees.
    struct Node* root1 = newNode(1);
    root1->left = newNode(3);
    root1->right = newNode(2);
    root1->right->left = newNode(5);
    root1->right->right = newNode(4);
 
    struct Node* root2 = newNode(1);
    root2->left = newNode(2);
    root2->right = newNode(3);
    root2->left->left = newNode(4);
    root2->left->right = newNode(5);
 
    areAnagrams(root1, root2) ? cout << "Yes"
                              : cout << "No";
    return 0;
}


Java




/* Iterative program to check if two trees
are level by level anagram. */
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Queue;
 
public class GFG {
    // A Binary Tree Node
    static class Node {
        Node left, right;
        int data;
        Node(int data)
        {
            this.data = data;
            left = null;
            right = null;
        }
    }
 
    // Returns true if trees with root1 and root2
    // are level by level anagram, else returns false.
    static boolean areAnagrams(Node root1, Node root2)
    {
        // Base Cases
        if (root1 == null && root2 == null)
            return true;
        if (root1 == null || root2 == null)
            return false;
 
        // start level order traversal of two trees
        // using two queues.
        Queue<Node> q1 = new LinkedList<Node>();
        Queue<Node> q2 = new LinkedList<Node>();
        q1.add(root1);
        q2.add(root2);
 
        while (true) {
            // n1 (queue size) indicates number of
            // Nodes at current level in first tree
            // and n2 indicates number of nodes in
            // current level of second tree.
            int n1 = q1.size(), n2 = q2.size();
 
            // If n1 and n2 are different
            if (n1 != n2)
                return false;
 
            // If level order traversal is over
            if (n1 == 0)
                break;
 
            // Dequeue all Nodes of current level and
            // Enqueue all Nodes of next level
            ArrayList<Integer> curr_level1
                = new ArrayList<>();
            ArrayList<Integer> curr_level2
                = new ArrayList<>();
            while (n1 > 0) {
                Node node1 = q1.peek();
                q1.remove();
                if (node1.left != null)
                    q1.add(node1.left);
                if (node1.right != null)
                    q1.add(node1.right);
                n1--;
 
                Node node2 = q2.peek();
                q2.remove();
                if (node2.left != null)
                    q2.add(node2.left);
                if (node2.right != null)
                    q2.add(node2.right);
 
                curr_level1.add(node1.data);
                curr_level2.add(node2.data);
            }
 
            // Check if nodes of current levels are
            // anagrams or not.
            Collections.sort(curr_level1);
            Collections.sort(curr_level2);
 
            if (!curr_level1.equals(curr_level2))
                return false;
        }
 
        return true;
    }
 
    // Driver program to test above functions
    public static void main(String args[])
    {
        // Constructing both the trees.
        Node root1 = new Node(1);
        root1.left = new Node(3);
        root1.right = new Node(2);
        root1.right.left = new Node(5);
        root1.right.right = new Node(4);
 
        Node root2 = new Node(1);
        root2.left = new Node(2);
        root2.right = new Node(3);
        root2.left.left = new Node(4);
        root2.left.right = new Node(5);
 
        System.out.println(
            areAnagrams(root1, root2) ? "Yes" : "No");
    }
}
// This code is contributed by Sumit Ghosh


Python3




# Iterative program to check if two
# trees are level by level anagram
 
# A Binary Tree Node
# Utility function to create a
# new tree Node
 
 
class newNode:
    def __init__(self, data):
        self.data = data
        self.left = self.right = None
 
# Returns true if trees with root1
# and root2 are level by level
# anagram, else returns false.
 
 
def areAnagrams(root1, root2):
 
    # Base Cases
    if (root1 == None and root2 == None):
        return True
    if (root1 == None or root2 == None):
        return False
 
    # start level order traversal of
    # two trees using two queues.
    q1 = []
    q2 = []
    q1.append(root1)
    q2.append(root2)
 
    while (1):
 
        # n1 (queue size) indicates number
        # of Nodes at current level in first
        # tree and n2 indicates number of nodes
        # in current level of second tree.
        n1 = len(q1)
        n2 = len(q2)
 
        # If n1 and n2 are different
        if (n1 != n2):
            return False
 
        # If level order traversal is over
        if (n1 == 0):
            break
 
        # Dequeue all Nodes of current level
        # and Enqueue all Nodes of next level
        curr_level1 = []
        curr_level2 = []
        while (n1 > 0):
            node1 = q1[0]
            q1.pop(0)
            if (node1.left != None):
                q1.append(node1.left)
            if (node1.right != None):
                q1.append(node1.right)
            n1 -= 1
 
            node2 = q2[0]
            q2.pop(0)
            if (node2.left != None):
                q2.append(node2.left)
            if (node2.right != None):
                q2.append(node2.right)
 
            curr_level1.append(node1.data)
            curr_level2.append(node2.data)
 
        # Check if nodes of current levels
        # are anagrams or not.
        curr_level1.sort()
        curr_level2.sort()
        if (curr_level1 != curr_level2):
            return False
 
    return True
 
 
# Driver Code
if __name__ == '__main__':
 
    # Constructing both the trees.
    root1 = newNode(1)
    root1.left = newNode(3)
    root1.right = newNode(2)
    root1.right.left = newNode(5)
    root1.right.right = newNode(4)
 
    root2 = newNode(1)
    root2.left = newNode(2)
    root2.right = newNode(3)
    root2.left.left = newNode(4)
    root2.left.right = newNode(5)
    if areAnagrams(root1, root2):
        print("Yes")
    else:
        print("No")
 
# This code is contributed
# by SHUBHAMSINGH10


C#




/* Iterative program to check if two trees
are level by level anagram. */
using System;
using System.Collections.Generic;
 
class GFG {
    // A Binary Tree Node
    public class Node {
        public Node left, right;
        public int data;
        public Node(int data)
        {
            this.data = data;
            left = null;
            right = null;
        }
    }
 
    // Returns true if trees with root1
    // and root2 are level by level anagram,
    // else returns false.
    static Boolean areAnagrams(Node root1, Node root2)
    {
        // Base Cases
        if (root1 == null && root2 == null)
            return true;
        if (root1 == null || root2 == null)
            return false;
 
        // start level order traversal of two trees
        // using two queues.
        Queue<Node> q1 = new Queue<Node>();
        Queue<Node> q2 = new Queue<Node>();
        q1.Enqueue(root1);
        q2.Enqueue(root2);
 
        while (true) {
            // n1 (queue size) indicates number of
            // Nodes at current level in first tree
            // and n2 indicates number of nodes in
            // current level of second tree.
            int n1 = q1.Count, n2 = q2.Count;
 
            // If n1 and n2 are different
            if (n1 != n2)
                return false;
 
            // If level order traversal is over
            if (n1 == 0)
                break;
 
            // Dequeue all Nodes of current level and
            // Enqueue all Nodes of next level
            List<int> curr_level1 = new List<int>();
            List<int> curr_level2 = new List<int>();
            while (n1 > 0) {
                Node node1 = q1.Peek();
                q1.Dequeue();
                if (node1.left != null)
                    q1.Enqueue(node1.left);
                if (node1.right != null)
                    q1.Enqueue(node1.right);
                n1--;
 
                Node node2 = q2.Peek();
                q2.Dequeue();
                if (node2.left != null)
                    q2.Enqueue(node2.left);
                if (node2.right != null)
                    q2.Enqueue(node2.right);
 
                curr_level1.Add(node1.data);
                curr_level2.Add(node2.data);
            }
 
            // Check if nodes of current levels are
            // anagrams or not.
            curr_level1.Sort();
            curr_level2.Sort();
 
            for (int i = 0; i < curr_level1.Count; i++)
                if (curr_level1[i] != curr_level2[i])
                    return false;
        }
        return true;
    }
 
    // Driver Code
    public static void Main(String[] args)
    {
        // Constructing both the trees.
        Node root1 = new Node(1);
        root1.left = new Node(3);
        root1.right = new Node(2);
        root1.right.left = new Node(5);
        root1.right.right = new Node(4);
 
        Node root2 = new Node(1);
        root2.left = new Node(2);
        root2.right = new Node(3);
        root2.left.left = new Node(4);
        root2.left.right = new Node(5);
 
        Console.WriteLine(areAnagrams(root1, root2) ? "Yes"
                                                    : "No");
    }
}
 
// This code is contributed by Arnab Kundu


Javascript




<script>
 
// Iterative program to check if two
// trees are level by level anagram
 
// A Binary Tree Node
// Utility function to create a
// new tree Node
class newNode{
    constructor(data){
        this.data = data
        this.left = this.right = null
    }
}
         
// Returns true if trees with root1
// and root2 are level by level
// anagram, else returns false.
function areAnagrams(root1, root2){
 
    // Base Cases
    if (root1 == null && root2 == null)
        return true
    if (root1 == null || root2 == null)
        return false
 
    // start level order traversal of
    // two trees using two queues.
    let q1 = []
    let q2 = []
    q1.push(root1)
    q2.push(root2)
 
    while (1){
     
        // n1 (queue size) indicates number
        // of Nodes at current level in first
        // tree and n2 indicates number of nodes
        // in current level of second tree.
        let n1 = q1.length
        let n2 = q2.length
 
        // If n1 and n2 are different
        if (n1 != n2)
            return false
 
        // If level order traversal is over
        if (n1 == 0)
            break
 
        // Dequeue all Nodes of current level
        // and Enqueue all Nodes of next level
        let curr_level1 = []
        let curr_level2 = []
        while (n1 > 0){
            let node1 = q1.shift()
     
            if (node1.left != null)
                q1.push(node1.left)
            if (node1.right != null)
                q1.push(node1.right)
            n1 -= 1
 
            let node2 = q2.shift()
 
            if (node2.left != null)
                q2.push(node2.left)
            if (node2.right != null)
                q2.push(node2.right)
 
            curr_level1.push(node1.data)
            curr_level2.push(node2.data)
        }
             
        // Check if nodes of current levels
        // are anagrams or not.
        curr_level1.sort()
        curr_level2.sort()
        if (curr_level1.join() != curr_level2.join())
            return false
    }
    return true
}
 
// Driver Code
     
// Constructing both the trees.
let root1 = new newNode(1)
root1.left = new newNode(3)
root1.right = new newNode(2)
root1.right.left = new newNode(5)
root1.right.right = new newNode(4)
 
let root2 = new newNode(1)
root2.left = new newNode(2)
root2.right = new newNode(3)
root2.left.left = new newNode(4)
root2.left.right = new newNode(5)
if(areAnagrams(root1, root2))
    document.write("Yes","</br>"
else
    document.write("No","</br>")
 
// This code is contributed by shinjanpatra
 
</script>


Output

Yes







Time Complexity: O(n log n), Where n is the number of nodes. 
Auxiliary Space: O(n)

Note: In the above program we are comparing the vectors storing each level of a tree directly using not equal to function ‘ != ‘ which compares the vectors first on the basis of their size and then on the basis of their content, hence saving our work of iteratively comparing the vectors.

Efficient Approach:

We can solve the problem in O(n) time complexity by using Hash tables during level order traversal. The idea is to do a level order traversal and in each level check whether the level is an anagram with help of hash tables.

C++




/* Iterative program to check if two trees are level
  by level anagram. */
#include <bits/stdc++.h>
using namespace std;
 
// A Binary Tree Node
struct Node {
    struct Node *left, *right;
    int data;
};
 
// Returns true if trees with root1 and root2
// are level by level anagram, else returns false.
bool areAnagrams(Node* root1, Node* root2)
{
    // Base Cases
    if (root1 == NULL && root2 == NULL)
        return true;
    if (root1 == NULL || root2 == NULL)
        return false;
 
    // start level order traversal of two trees
    // using two queues.
    queue<Node*> q1, q2;
    q1.push(root1);
    q2.push(root2);
 
    // Hashmap to store the elements that occur in each
    // level.
    unordered_map<int, int> m;
 
    while (!q1.empty() && !q2.empty()) {
        // n1 (queue size) indicates number of Nodes
        // at current level in first tree and n2 indicates
        // number of nodes in current level of second tree.
        int n1 = q1.size(), n2 = q2.size();
 
        // If n1 and n2 are different
        if (n1 != n2)
            return false;
 
        // If level order traversal is over
        if (n1 == 0)
            break;
 
        // Dequeue all Nodes of current level and
        // Enqueue all Nodes of next level
        while (n1--) {
            Node* node1 = q1.front();
            q1.pop();
 
            // Insert element into hashmap
            m[node1->data]++;
 
            // Insert left and right nodes into queue if
            // exists.
            if (node1->left != NULL)
                q1.push(node1->left);
            if (node1->right != NULL)
                q1.push(node1->right);
        }
 
        while (n2--) {
            Node* node2 = q2.front();
            q2.pop();
 
            // if element from second tree isn't present in
            // the first tree of same level then it can't be
            // an anagram.
            if (m.find(node2->data) == m.end())
                return false;
 
            // Reduce frequency of element if present else
            // adds it element to hash map with negative
            // frequency.
            m[node2->data]--;
 
            // If frequency of the element becomes zero then
            // remove the element from hashmap.
            if (m[node2->data] == 0)
                m.erase(node2->data);
 
            // Insert left and right nodes into queue if
            // exists.
            if (node2->left != NULL)
                q2.push(node2->left);
            if (node2->right != NULL)
                q2.push(node2->right);
        }
 
        // If nodes of current levels are anagrams the
        // hashmap wouldn't contain any elements.
        if (m.size() > 0)
            return false;
    }
    if (q1.empty() && q2.empty())
        return true;
    return false;
}
 
// Utility function to create a new tree Node
Node* newNode(int data)
{
    Node* temp = new Node;
    temp->data = data;
    temp->left = temp->right = NULL;
    return temp;
}
 
// Driver program to test above functions
int main()
{
    // Constructing both the trees.
    struct Node* root1 = newNode(1);
    root1->left = newNode(3);
    root1->right = newNode(2);
    root1->right->left = newNode(5);
    root1->right->right = newNode(4);
 
    struct Node* root2 = newNode(1);
    root2->left = newNode(2);
    root2->right = newNode(3);
    root2->left->left = newNode(4);
    root2->left->right = newNode(5);
 
    areAnagrams(root1, root2) ? cout << "Yes"
                              : cout << "No";
    return 0;
}
 
// This code is contributed by Kasina Dheeraj.


Java




// Java program for above approach
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
 
// A Binary Tree Node
class Node {
    Node left, right;
    int data;
 
    Node(int data)
    {
        this.data = data;
        left = right = null;
    }
}
 
class BinaryTree {
 
    // Returns true if trees with root1 and root2
    // are level by level anagram, else returns false.
    public static boolean areAnagrams(Node root1,
                                      Node root2)
    {
        // Base Cases
        if (root1 == null && root2 == null)
            return true;
        if (root1 == null || root2 == null)
            return false;
 
        // start level order traversal of two trees
        // using two queues.
        Queue<Node> q1 = new LinkedList<Node>();
        Queue<Node> q2 = new LinkedList<Node>();
        q1.add(root1);
        q2.add(root2);
 
        // Hashmap to store the elements that occur in each
        // level.
        Map<Integer, Integer> m
            = new HashMap<Integer, Integer>();
 
        while (!q1.isEmpty() && !q2.isEmpty()) {
            // n1 (queue size) indicates number of Nodes
            // at current level in first tree and n2
            // indicates number of nodes in current level of
            // second tree.
            int n1 = q1.size(), n2 = q2.size();
 
            // If n1 and n2 are different
            if (n1 != n2)
                return false;
 
            // If level order traversal is over
            if (n1 == 0)
                break;
 
            // Dequeue all Nodes of current level and
            // Enqueue all Nodes of next level
            while (n1-- > 0) {
                Node node1 = q1.peek();
                q1.remove();
 
                // Insert element into hashmap
                m.put(node1.data,
                      m.getOrDefault(node1.data, 0) + 1);
 
                // Insert left and right nodes into queue if
                // exists.
                if (node1.left != null)
                    q1.add(node1.left);
                if (node1.right != null)
                    q1.add(node1.right);
            }
 
            while (n2-- > 0) {
                Node node2 = q2.peek();
                q2.remove();
 
                // if element from second tree isn't present
                // in the first tree of same level then it
                // can't be an anagram.
                if (!m.containsKey(node2.data))
                    return false;
 
                // Reduce frequency of element if present
                // else adds it element to hash map with
                // negative frequency.
                m.put(node2.data, m.get(node2.data) - 1);
 
                // If frequency of the element becomes zero
                // then remove the element from hashmap.
                if (m.get(node2.data) == 0)
                    m.remove(node2.data);
 
                // Insert left and right nodes into queue if
                // exists.
                if (node2.left != null)
                    q2.add(node2.left);
                if (node2.right != null)
                    q2.add(node2.right);
            }
 
            // If nodes of current levels are anagrams the
            // hashmap wouldn't contain any elements.
            if (m.size() > 0)
                return false;
        }
        if (q1.isEmpty() && q2.isEmpty())
            return true;
        return false;
    }
 
    // Utility function to create a new tree Node
    public static Node newNode(int data)
    {
        Node temp = new Node(data);
        return temp;
    }
 
    // Driver program to test above functions
    public static void main(String args[])
    {
        // Constructing both the trees.
        Node root1 = newNode(1);
        root1.left = newNode(3);
        root1.right = newNode(2);
        root1.right.left = newNode(5);
        root1.right.right = newNode(4);
 
        Node root2 = newNode(1);
        root2.left = newNode(2);
        root2.right = newNode(3);
        root2.left.left = newNode(4);
        root2.left.right = newNode(5);
 
        if (areAnagrams(root1, root2))
            System.out.println("Yes");
        else
            System.out.println("No");
    }
}
 
// This code is contributed by adityamaharshi21


Python3




# Python code for above approach
 
# A Binary Tree Node
 
 
class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None
 
# Returns true if trees with root1 and root2
# are level by level anagram, else returns false.
 
 
def areAnagrams(root1, root2):
    # Base Cases
    if (root1 == None and root2 == None):
        return True
    if (root1 == None or root2 == None):
        return False
 
    # start level order traversal of two trees
    # using two queues.
    q1 = []
    q2 = []
    q1.append(root1)
    q2.append(root2)
 
    # Hashmap to store the elements that occur in each
    # level.
    m = {}
 
    while (len(q1) > 0 and len(q2) > 0):
        # n1 (queue size) indicates number of Nodes
        # at current level in first tree and n2 indicates
        # number of nodes in current level of second tree.
        n1 = len(q1)
        n2 = len(q2)
 
        # If n1 and n2 are different
        if (n1 != n2):
            return False
 
        # If level order traversal is over
        if (n1 == 0):
            break
 
        # Dequeue all Nodes of current level and
        # Enqueue all Nodes of next level
        while (n1 > 0):
            node1 = q1.pop(0)
 
            # Insert element into hashmap
            m[node1.data] = m.get(node1.data, 0) + 1
 
            # Insert left and right nodes into queue if
            # exists.
            if (node1.left != None):
                q1.append(node1.left)
            if (node1.right != None):
                q1.append(node1.right)
            n1 -= 1
 
        while (n2 > 0):
            node2 = q2.pop(0)
 
            # if element from second tree isn't present in
            # the first tree of same level then it can't be
            # an anagram.
            if (m.get(node2.data, 0) == 0):
                return False
 
            # Reduce frequency of element if present else
            # adds it element to hash map with negative
            # frequency.
            m[node2.data] = m.get(node2.data, 0) - 1
 
            # If frequency of the element becomes zero then
            # remove the element from hashmap.
            if (m[node2.data] == 0):
                m.pop(node2.data)
 
            # Insert left and right nodes into queue if
            # exists.
            if (node2.left != None):
                q2.append(node2.left)
            if (node2.right != None):
                q2.append(node2.right)
            n2 -= 1
 
        # If nodes of current levels are anagrams the
        # hashmap wouldn't contain any elements.
        if (len(m) > 0):
            return False
 
    if(len(q1) == 0 and len(q2) == 0):
        return True
    return False
 
# Utility function to create a new tree Node
 
 
def newNode(data):
    temp = Node(data)
    temp.left = None
    temp.right = None
    return temp
 
 
# Driver program to test above functions
if __name__ == '__main__':
 
    # Constructing both the trees.
    root1 = newNode(1)
    root1.left = newNode(3)
    root1.right = newNode(2)
    root1.right.left = newNode(5)
    root1.right.right = newNode(4)
 
    root2 = newNode(1)
    root2.left = newNode(2)
    root2.right = newNode(3)
    root2.left.left = newNode(4)
    root2.left.right = newNode(5)
 
    if (areAnagrams(root1, root2)):
        print("Yes")
    else:
        print("No")
 
# This code is contributed by adityamaharshi21


C#




// C# program for above approach
using System;
using System.Collections.Generic;
 
// A Binary Tree Node
public class gfg {
    public class Node {
        public Node left, right;
        public int data;
    }
 
    // Returns true if trees with root1 and root2
    // are level by level anagram, else returns false.
    public static bool areAnagrams(Node root1, Node root2)
    {
        // Base Cases
        if (root1 == null && root2 == null)
            return true;
        if (root1 == null || root2 == null)
            return false;
 
        // start level order traversal of two trees
        // using two queues.
        Queue<Node> q1 = new Queue<Node>();
        Queue<Node> q2 = new Queue<Node>();
        q1.Enqueue(root1);
        q2.Enqueue(root2);
 
        // Hashmap to store the elements that occur in each
        // level.
        Dictionary<int, int> m = new Dictionary<int, int>();
 
        while (q1.Count > 0 && q2.Count > 0) {
            // n1 (queue size) indicates number of Nodes
            // at current level in first tree and n2
            // indicates number of nodes in current level of
            // second tree.
            int n1 = q1.Count;
            int n2 = q2.Count;
 
            // If n1 and n2 are different
            if (n1 != n2)
                return false;
 
            // If level order traversal is over
            if (n1 == 0)
                break;
 
            // Dequeue all Nodes of current level and
            // Enqueue all Nodes of next level
            while (n1-- > 0) {
                Node node1 = q1.Dequeue();
 
                // Insert element into hashmap
                if (m.ContainsKey(node1.data)) {
                    m[node1.data]++;
                }
                else {
                    m.Add(node1.data, 1);
                }
 
                // Insert left and right nodes into queue if
                // exists.
                if (node1.left != null)
                    q1.Enqueue(node1.left);
                if (node1.right != null)
                    q1.Enqueue(node1.right);
            }
 
            while (n2-- > 0) {
                Node node2 = q2.Dequeue();
 
                // if element from second tree isn't present
                // in the first tree of same level then it
                // can't be an anagram.
                if (!m.ContainsKey(node2.data))
                    return false;
 
                // Reduce frequency of element if present
                // else adds it element to hash map with
                // negative frequency.
                m[node2.data]--;
 
                // If frequency of the element becomes zero
                // then remove the element from hashmap.
                if (m[node2.data] == 0)
                    m.Remove(node2.data);
 
                // Insert left and right nodes into queue if
                // exists.
                if (node2.left != null)
                    q2.Enqueue(node2.left);
                if (node2.right != null)
                    q2.Enqueue(node2.right);
            }
 
            // If nodes of current levels are anagrams the
            // hashmap wouldn't contain any elements.
            if (m.Count > 0)
                return false;
        }
        if (q1.Count == 0 && q2.Count == 0)
            return true;
        return false;
    }
 
    // Utility function to create a new tree Node
    public static Node newNode(int data)
    {
        Node temp = new Node();
        temp.data = data;
        temp.left = temp.right = null;
        return temp;
    }
 
    // Driver program to test above functions
    public static void Main(String[] args)
    {
        // Constructing both the trees.
        Node root1 = newNode(1);
        root1.left = newNode(3);
        root1.right = newNode(2);
        root1.right.left = newNode(5);
        root1.right.right = newNode(4);
 
        Node root2 = newNode(1);
        root2.left = newNode(2);
        root2.right = newNode(3);
        root2.left.left = newNode(4);
        root2.left.right = newNode(5);
 
        if (areAnagrams(root1, root2))
            Console.WriteLine("Yes");
        else
            Console.WriteLine("No");
    }
}
 
// This code is contributed by adityamaharshi21


Javascript




// JavaScript code for above approach
 
// A Binary Tree Node
class Node {
    constructor(data) {
        this.data = data;
        this.left = null;
        this.right = null;
    }
}
let root1, root2;
// Returns true if trees with root1 and root2
// are level by level anagram, else returns false.
function areAnagrams(root1, root2) {
    // Base Cases
    if (root1 == null && root2 == null)
        return true;
    if (root1 == null || root2 == null)
        return false;
 
    // start level order traversal of two trees
    // using two queues.
    let q1 = [];
    let q2 = [];
    q1.push(root1);
    q2.push(root2);
 
    // Hashmap to store the elements that occur in each
    // level.
    let m = new Map();
 
    while (q1.length != 0 && q2.length != 0) {
        // n1 (queue size) indicates number of Nodes
        // at current level in first tree and n2 indicates
        // number of nodes in current level of second tree.
        let n1 = q1.length;
        let n2 = q2.length;
 
        // If n1 and n2 are different
        if (n1 != n2)
            return false;
 
        // If level order traversal is over
        if (n1 == 0)
            break;
 
        // Dequeue all Nodes of current level and
        // Enqueue all Nodes of next level
        while (n1--) {
            let node1 = q1[0];
            q1.shift();
            // Insert element into hashmap
            if (m.has(node1.data)) {
                m.set(node1.data, m.get(node1.data) + 1);
            } else {
                m.set(node1.data, 1);
            }
 
            // Insert left and right nodes into queue if
            // exists.
            if (node1.left != null)
                q1.push(node1.left);
            if (node1.right != null)
                q1.push(node1.right);
        }
 
        while (n2--) {
            let node2 = q2.shift();
 
            // if element from second tree isn't present in
            // the first tree of same level then it can't be
            // an anagram.
            if (!m.has(node2.data))
                return false;
 
            // Reduce frequency of element if present else
            // adds it element to hash map with negative
            // frequency.
            m.set(node2.data, m.get(node2.data) - 1);
 
            // If frequency of the element becomes zero then
            // remove the element from hashmap.
            if (m.get(node2.data) == 0)
                m.delete(node2.data);
 
            // Insert left and right nodes into queue if
            // exists.
            if (node2.left != null)
                q2.push(node2.left);
            if (node2.right != null)
                q2.push(node2.right);
        }
 
        // If nodes of current levels are anagrams the
        // hashmap wouldn't contain any elements.
        if (m.size > 0)
            return false;
    }
    if (q1.length == 0 && q2.length == 0)
        return true;
    return false;
}
 
 
// Driver program to test above functions
// Constructing both the trees.
root1 = new Node(1);
root1.left = new Node(3);
root1.right = new Node(2);
root1.right.left = new Node(5);
root1.right.right = new Node(4);
 
root2 = new Node(1);
root2.left = new Node(2);
root2.right = new Node(3);
root2.left.left = new Node(4);
root2.left.right = new Node(5);
 
console.log(areAnagrams(root1, root2) ? 'Yes' : 'No');
 
// This code is contributed by adityamaharshi21


Output

Yes







Time complexity: O(N), where N is a maximum number of nodes in either of the trees.
Auxiliary Space: O(N)

 



Last Updated : 08 Feb, 2024
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads