1
+ package Algorithms .tree ;
2
+
3
+ import java .util .*;
4
+
5
+
6
+ public class LargestCommonSubtrees {
7
+ /*
8
+ * Function: Find all the common subtrees root that have most number
9
+ */
10
+ private static class TreeNode {
11
+ int val ;
12
+ ArrayList <TreeNode > subNodes ;
13
+ public TreeNode (int val , ArrayList <TreeNode > subNodes ) {
14
+ this .val = val ;
15
+ this .subNodes = subNodes ;
16
+ }
17
+ }
18
+
19
+ public static void main (String [] args ) {
20
+ /*
21
+ * 1
22
+ *
23
+ * / \ \
24
+ * 2 3 4
25
+ * / \ / \
26
+ * 5 6 8 9
27
+ * \ \
28
+ * 7 10
29
+ * */
30
+ TreeNode r1 = new TreeNode (1 , new ArrayList <TreeNode >());
31
+ TreeNode r2 = new TreeNode (2 , new ArrayList <TreeNode >());
32
+ TreeNode r3 = new TreeNode (3 , new ArrayList <TreeNode >());
33
+ TreeNode r4 = new TreeNode (4 , new ArrayList <TreeNode >());
34
+ TreeNode r5 = new TreeNode (5 , new ArrayList <TreeNode >());
35
+ TreeNode r6 = new TreeNode (6 , new ArrayList <TreeNode >());
36
+ TreeNode r7 = new TreeNode (7 , new ArrayList <TreeNode >());
37
+ TreeNode r8 = new TreeNode (8 , new ArrayList <TreeNode >());
38
+ TreeNode r9 = new TreeNode (9 , new ArrayList <TreeNode >());
39
+ TreeNode r10 = new TreeNode (10 , new ArrayList <TreeNode >());
40
+
41
+ r1 .subNodes .add (r2 );
42
+ r1 .subNodes .add (r3 );
43
+ r1 .subNodes .add (r4 );
44
+
45
+ r2 .subNodes .add (r5 );
46
+ r2 .subNodes .add (r6 );
47
+
48
+ r6 .subNodes .add (r7 );
49
+
50
+ r4 .subNodes .add (r8 );
51
+ r4 .subNodes .add (r9 );
52
+
53
+ r9 .subNodes .add (r10 );
54
+
55
+ ArrayList <ArrayList <TreeNode >> ret = largestCommonSubtrees (r1 );
56
+ for (ArrayList <TreeNode > arrayl : ret ) {
57
+ for (TreeNode t : arrayl ) {
58
+ System .out .println (t .val );
59
+ }
60
+ }
61
+
62
+ }
63
+
64
+ public static ArrayList <ArrayList <TreeNode >> largestCommonSubtrees (TreeNode root ) {
65
+ if (root == null ) {
66
+ return null ;
67
+ }
68
+
69
+ ArrayList <ArrayList <TreeNode >> ret = new ArrayList <ArrayList <TreeNode >>();
70
+
71
+ // store all the tree nodes to a arrayList.
72
+ ArrayList <TreeNode > nodes = new ArrayList <TreeNode >();
73
+ traversalTree (root , nodes );
74
+
75
+ int maxNum = 0 ;
76
+
77
+ HashMap <Integer , Integer > hash = new HashMap <Integer , Integer >();
78
+
79
+ TreeNode r1 = null ;
80
+ TreeNode r2 = null ;
81
+
82
+
83
+ // compare all the nodes.
84
+ int size = nodes .size ();
85
+ for (int i = 0 ; i < size ; i ++) {
86
+ for (int j = 0 ; j < size ; j ++) {
87
+ if (i == j ) {
88
+ continue ;
89
+ }
90
+ int num = compareTree (nodes .get (i ), nodes .get (j ), hash );
91
+ if (num > maxNum ) {
92
+ ArrayList <TreeNode > iden = new ArrayList <TreeNode >();
93
+ iden .add (nodes .get (i ));
94
+ iden .add (nodes .get (j ));
95
+
96
+ ret .add (iden );
97
+ r1 = nodes .get (i );
98
+ r2 = nodes .get (j );
99
+ }
100
+ }
101
+ }
102
+
103
+ ArrayList <ArrayList <TreeNode >> retNew = new ArrayList <ArrayList <TreeNode >>();
104
+ retNew .add (new ArrayList <TreeNode >());
105
+ retNew .get (0 ).add (r1 );
106
+ retNew .get (0 ).add (r2 );
107
+ return retNew ;
108
+ }
109
+
110
+
111
+ // compare two tree, if same, return the number of leafs. if no, return -1;
112
+ public static int compareTree (TreeNode r1 , TreeNode r2 , HashMap <Integer , Integer > hash ) {
113
+ if (r1 == null && r2 == null ) {
114
+ return 0 ;
115
+ }
116
+
117
+ if (r1 == null || r2 == null ) {
118
+ return -1 ;
119
+ }
120
+
121
+ // the number of subtrees should be same.
122
+ if (r1 .subNodes .size () != r2 .subNodes .size ()) {
123
+ return -1 ;
124
+ }
125
+
126
+ int num = 1 ; // the root itself.
127
+
128
+ for (int i = 0 ; i < r1 .subNodes .size (); i ++) {
129
+ // get the subNode of r1.
130
+ TreeNode subNode1 = r1 .subNodes .get (i );
131
+ TreeNode subNode2 = r2 .subNodes .get (i );
132
+
133
+ int HashCode = hashCode (subNode1 , subNode2 );
134
+
135
+ Integer numNode = hash .get (HashCode );
136
+ if (numNode == null ) {
137
+ numNode = compareTree (subNode1 , subNode2 , hash );
138
+ }
139
+
140
+ if (numNode == -1 ) {
141
+ // not the same, should return;
142
+ num = -1 ;
143
+ break ;
144
+ } else {
145
+ num += numNode ;
146
+ continue ;
147
+ }
148
+ }
149
+
150
+ int hashCodeRoot = hashCode (r1 , r2 );
151
+ hash .put (hashCodeRoot , num );
152
+
153
+ return num ;
154
+ }
155
+
156
+ public static int hashCode (TreeNode r1 , TreeNode r2 ) {
157
+ int hash = r1 .hashCode () * 31 + r2 .hashCode ();
158
+ return hash ;
159
+ }
160
+
161
+ public static void traversalTree (TreeNode root , ArrayList <TreeNode > ret ) {
162
+ if (root == null ) {
163
+ return ;
164
+ }
165
+
166
+ ret .add (root );
167
+
168
+ // add all the sub nodes.
169
+ if (root .subNodes != null ) {
170
+ for (TreeNode t : root .subNodes ) {
171
+ traversalTree (t , ret );
172
+ }
173
+ }
174
+ }
175
+
176
+
177
+ }
0 commit comments