Given two n-ary trees, determine whether they are mirror images of each other. Each tree is described by e edges, where e denotes the number of edges in both trees. Two arrays A[]and B[] are provided, where each array contains 2*e space-separated values representing the edges of both trees. Each edge is represented by two integers u and v, indicating an edge between node u and node v in the respective tree.
The task is to check whether the two trees are mirror images of each other.
Examples:
Input: n = 3, e = 2, A[] = [1, 2, 1, 3], B[] = [1, 3, 1, 2]
Output: True
Explanation: As we can clearly see, the second tree is the mirror image of the first.Input: n = 3, e = 2, A[] = [1, 2, 1, 3], B[] = [1, 2, 1, 3]
Output: False
Explanation: As we can clearly see, the second tree isn't mirror image of the first.
1 1
/ \ / \
2 3 2 3
Using Hash Map - O(e) time and O(n + e) space
The main idea is to use a
Hash Map or Dictionaryto store the relationships between nodes in the first tree. They key in the map is node number and values is a stack of nodes connected with it (or children of it) from left to right.
We then traverse the second tree and check if the children of the nodes are in reverse order compared to the first tree. This is how we check if the two trees are mirrors.
Below are detailed steps:
- For each edge in the first tree, push the connected nodes into the stack of the parent node in the map.
- For each node
Xin the second tree, compare the connected nodea(top of the stack for nodeXin the map) with the connected nodeb(the current child of nodeXin the second tree). - If the values
aandbdon't match, returnfalse, indicating the trees are not mirror images of each other. - If the values match, pop node
Xfrom the stack (as it has been correctly matched in the second tree).
#include <iostream>
#include <unordered_map>
#include <stack>
using namespace std;
int checkMirror(int n, int e, int A[], int B[]) {
unordered_map<int, stack<int>> mp;
for (int i = 0; i < e; i++) {
mp[A[2*i]].push(A[2*i+1]);
}
for (int i = 0; i < e; i++) {
if (mp[B[2*i]].top() != B[2*i+1]) {
return 0;
}
mp[B[2*i]].pop();
}
return 1;
}
int main() {
int n = 3, e = 2;
int A[] = {1, 2, 1, 3};
int B[] = {1, 3, 1, 2};
if (checkMirror(n, e, A, B))
cout << "1";
else
cout << "0";
return 0;
}
import java.util.*;
public class GfG {
public static int checkMirror(int n, int e, int[] A, int[] B) {
HashMap<Integer, Stack<Integer>> mp = new HashMap<>();
for (int i = 0; i < e; i++) {
mp.putIfAbsent(A[2 * i], new Stack<>());
mp.get(A[2 * i]).push(A[2 * i + 1]);
}
for (int i = 0; i < e; i++) {
if (mp.get(B[2 * i]).peek() != B[2 * i + 1]) {
return 0;
}
mp.get(B[2 * i]).pop();
}
return 1;
}
public static void main(String[] args) {
int n = 3, e = 2;
int[] A = {1, 2, 1, 3};
int[] B = {1, 3, 1, 2};
if (checkMirror(n, e, A, B) == 1)
System.out.println("1");
else
System.out.println("0");
}
}
def checkMirror(n, e, A, B):
mp = {}
for i in range(e):
if A[2 * i] not in mp:
mp[A[2 * i]] = []
mp[A[2 * i]].append(A[2 * i + 1])
for i in range(e):
if mp[B[2 * i]][-1] != B[2 * i + 1]:
return 0
mp[B[2 * i]].pop()
return 1
if __name__ == '__main__':
n = 3
e = 2
A = [1, 2, 1, 3]
B = [1, 3, 1, 2]
if checkMirror(n, e, A, B):
print("1")
else:
print("0")
using System;
using System.Collections.Generic;
using System.Linq;
class GfG {
public static int CheckMirror(int n, int e, int[] A, int[] B) {
Dictionary<int, Stack<int>> mp = new Dictionary<int, Stack<int>>();
for (int i = 0; i < e; i++) {
if (!mp.ContainsKey(A[2 * i])) {
mp[A[2 * i]] = new Stack<int>();
}
mp[A[2 * i]].Push(A[2 * i + 1]);
}
for (int i = 0; i < e; i++) {
if (mp[B[2 * i]].Peek() != B[2 * i + 1]) {
return 0;
}
mp[B[2 * i]].Pop();
}
return 1;
}
static void Main() {
int n = 3, e = 2;
int[] A = {1, 2, 1, 3};
int[] B = {1, 3, 1, 2};
Console.WriteLine(CheckMirror(n, e, A, B) == 1 ? "1" : "0");
}
}
function checkMirror(n, e, A, B) {
const mp = {};
for (let i = 0; i < e; i++) {
if (!mp[A[2 * i]]) {
mp[A[2 * i]] = [];
}
mp[A[2 * i]].push(A[2 * i + 1]);
}
for (let i = 0; i < e; i++) {
if (mp[B[2 * i]][mp[B[2 * i]].length - 1] !== B[2 * i + 1]) {
return 0;
}
mp[B[2 * i]].pop();
}
return 1;
}
const n = 3, e = 2;
const A = [1, 2, 1, 3];
const B = [1, 3, 1, 2];
console.log(checkMirror(n, e, A, B) ? '1' : '0');
Output
1
Time Complexity: O(e) for both building the map and checking the second tree.
Auxiliary Space: O(n + e), where n is the number of nodes (which may be proportional to e in typical tree structures) and e is the number of edges.
Stack-Queue Mirror Tree Comparison Method - O(e) time and O(e) space
The approach uses stacks and queues to check if two n-ary trees are mirror images.
For tree 1, child nodes are stored in stacks, and for tree 2, child nodes are stored in queues. The trees are compared by popping nodes from the stack for tree 1 and dequeuing nodes from the queue for tree 2. If the nodes at each position match in reverse order, the trees are mirrors; otherwise, they are not. If all comparisons succeed, the function returns true; if any mismatch occurs, it returns
false.
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
int checkMirror(int n, int e, int A[], int B[]) {
// Create vectors to store stacks and queues for each node
vector<stack<int>> s;
vector<queue<int>> q;
// Initialize each vector element with an empty stack and queue
for (int i = 0; i <= n; i++) {
s.push_back(stack<int>());
queue<int> queue;
q.push_back(queue);
}
// Fill the stacks for tree 1 and queues for tree 2 based on given edges
for (int i = 0; i < 2 * e; i += 2) {
s[A[i]].push(A[i + 1]);
q[B[i]].push(B[i + 1]);
}
// Now, compare nodes of both trees by taking out elements from stack and queue
for (int i = 1; i <= n; i++) {
// Ensure both the stack and queue are not empty before comparing
while (!s[i].empty() && !q[i].empty()) {
int a = s[i].top();
s[i].pop();
int b = q[i].front();
q[i].pop();
// If the nodes don't match, the trees are not mirrors
if (a != b) {
return 0;
}
}
}
// If all comparisons are successful, return 1 (trees are mirror images)
return 1;
}
int main() {
int n = 3, e = 2;
int A[] = {1, 2, 1, 3};
int B[] = {1, 3, 1, 2};
// Check if the trees are mirror images and print the result
if (checkMirror(n, e, A, B) == 1) {
cout << "1";
} else {
cout << "0";
}
return 0;
}
import java.util.*;
public class GfG {
public static int checkMirror(int n, int e, int[] A, int[] B) {
// Create lists to store stacks and queues for each node
List<Stack<Integer>> s = new ArrayList<>();
List<Queue<Integer>> q = new ArrayList<>();
// Initialize each list element with an empty stack and queue
for (int i = 0; i <= n; i++) {
s.add(new Stack<>());
q.add(new LinkedList<>());
}
// Fill the stacks for tree 1 and queues for tree 2 based on given edges
for (int i = 0; i < 2 * e; i += 2) {
s.get(A[i]).push(A[i + 1]);
q.get(B[i]).offer(B[i + 1]);
}
// Now, compare nodes of both trees by taking out elements from stack and queue
for (int i = 1; i <= n; i++) {
// Ensure both the stack and queue are not empty before comparing
while (!s.get(i).isEmpty() && !q.get(i).isEmpty()) {
int a = s.get(i).pop();
int b = q.get(i).poll();
// If the nodes don't match, the trees are not mirrors
if (a != b) {
return 0;
}
}
}
// If all comparisons are successful, return 1 (trees are mirror images)
return 1;
}
public static void main(String[] args) {
int n = 3, e = 2;
int[] A = {1, 2, 1, 3};
int[] B = {1, 3, 1, 2};
// Check if the trees are mirror images and print the result
if (checkMirror(n, e, A, B) == 1) {
System.out.println("1");
} else {
System.out.println("0");
}
}
}
# Define the function to check mirror
def checkMirror(n, e, A, B):
# Create lists to store stacks and queues for each node
s = [[] for _ in range(n + 1)]
q = [[] for _ in range(n + 1)]
# Fill the stacks for tree 1 and queues for tree 2 based on given edges
for i in range(0, 2 * e, 2):
s[A[i]].append(A[i + 1])
q[B[i]].append(B[i + 1])
# Now, compare nodes of both trees by taking out elements from stack and queue
for i in range(1, n + 1):
# Ensure both the stack and queue are not empty before comparing
while s[i] and q[i]:
a = s[i].pop() # Pop from stack
b = q[i].pop(0) # Dequeue from queue
# If the nodes don't match, the trees are not mirrors
if a != b:
return 0
# If all comparisons are successful, return 1 (trees are mirror images)
return 1
if __name__ == '__main__':
n = 3
e = 2
A = [1, 2, 1, 3]
B = [1, 3, 1, 2]
# Check if the trees are mirror images and print the result
if checkMirror(n, e, A, B) == 1:
print("1")
else:
print("0")
using System;
using System.Collections.Generic;
class GfG {
public static int CheckMirror(int n, int e, int[] A, int[] B) {
// Create lists to store stacks and queues for each node
List<Stack<int>> s = new List<Stack<int>>();
List<Queue<int>> q = new List<Queue<int>>();
// Initialize each list element with an empty stack and queue
for (int i = 0; i <= n; i++) {
s.Add(new Stack<int>());
q.Add(new Queue<int>());
}
// Fill the stacks for tree 1 and queues for tree 2 based on given edges
for (int i = 0; i < 2 * e; i += 2) {
s[A[i]].Push(A[i + 1]);
q[B[i]].Enqueue(B[i + 1]);
}
// Now, compare nodes of both trees by taking out elements from stack and queue
for (int i = 1; i <= n; i++) {
// Ensure both the stack and queue are not empty before comparing
while (s[i].Count > 0 && q[i].Count > 0) {
int a = s[i].Pop();
int b = q[i].Dequeue();
// If the nodes don't match, the trees are not mirrors
if (a != b) {
return 0;
}
}
}
// If all comparisons are successful, return 1 (trees are mirror images)
return 1;
}
static void Main() {
int n = 3, e = 2;
int[] A = {1, 2, 1, 3};
int[] B = {1, 3, 1, 2};
// Check if the trees are mirror images and print the result
if (CheckMirror(n, e, A, B) == 1) {
Console.WriteLine("1");
} else {
Console.WriteLine("0");
}
}
}
function checkMirror(n, e, A, B) {
// Create arrays to store stacks and queues for each node
let s = Array.from({length: n + 1}, () => []);
let q = Array.from({length: n + 1}, () => []);
// Fill the stacks for tree 1 and queues for tree 2 based on given edges
for (let i = 0; i < 2 * e; i += 2) {
s[A[i]].push(A[i + 1]);
q[B[i]].push(B[i + 1]);
}
// Now, compare nodes of both trees by taking out elements from stack and queue
for (let i = 1; i <= n; i++) {
// Ensure both the stack and queue are not empty before comparing
while (s[i].length > 0 && q[i].length > 0) {
let a = s[i].pop();
let b = q[i].shift();
// If the nodes don't match, the trees are not mirrors
if (a !== b) {
return 0;
}
}
}
// If all comparisons are successful, return 1 (trees are mirror images)
return 1;
}
const n = 3, e = 2;
const A = [1, 2, 1, 3];
const B = [1, 3, 1, 2];
// Check if the trees are mirror images and print the result
console.log(checkMirror(n, e, A, B) === 1 ? "1" : "0");
Output
1
Time complexity: O(e), where e is the number of edges
Auxiliary space: O(e)
