// Java program to find all Duplicate Subtrees
import java.util.*;
class Node {
int data;
Node left, right;
Node(int x) {
data = x;
left = null;
right = null;
}
}
class GfG {
// Function to serialize all subtrees
// of a binary tree.
static int serializeTree(Node root, Map<Integer, Integer> map,
Map<String, Integer> strToInt, List<Node> ans, int[] idNum) {
if (root == null) return 0;
int left = serializeTree(root.left, map, strToInt, ans, idNum);
int right = serializeTree(root.right, map, strToInt, ans, idNum);
String val = Integer.toString(root.data);
// Subtree serialization
// left - root - right
String curr = "(" + left + ")" + val + "(" + right + ")";
// Assign an integer id for the serialized string.
int currId;
// If id already exists
if (strToInt.containsKey(curr)) {
currId = strToInt.get(curr);
}
// Else assign a new id.
else {
currId = idNum[0]++;
strToInt.put(curr, currId);
}
map.put(currId, map.getOrDefault(currId, 0) + 1);
// If such subtree already exists
// add root to answer
if (map.get(currId) == 2) {
ans.add(root);
}
return currId;
}
// Function to print all duplicate
// subtrees of a binary tree.
static List<Node> printAllDups(Node root) {
// Hash map to store count of
// subtrees.
Map<Integer, Integer> map = new HashMap<>();
Map<String, Integer> strToInt = new HashMap<>();
List<Node> ans = new ArrayList<>();
// Variable to assign unique integer id
// for each serialized string.
int[] idNum = {1};
// Function which will serialize all subtrees
// and store duplicate subtrees into answer.
serializeTree(root, map, strToInt, ans, idNum);
return ans;
}
static void preOrder(Node root) {
if (root == null) return;
System.out.print(root.data + " ");
preOrder(root.left);
preOrder(root.right);
}
public static void main(String[] args) {
Node root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.right.left = new Node(2);
root.right.right = new Node(4);
root.right.left.left = new Node(4);
List<Node> ans = printAllDups(root);
for (Node node : ans) {
preOrder(node);
System.out.println();
}
}
}