11package by .andd3dfx .tree .equivalent ;
22
3+ import java .util .ArrayDeque ;
34import java .util .ArrayList ;
5+ import java .util .Deque ;
46import java .util .HashMap ;
5- import java .util .HashSet ;
67import java .util .List ;
78import java .util .Map ;
89import java .util .Set ;
9- import java .util .stream . Collectors ;
10+ import java .util .function . ToIntFunction ;
1011
1112/**
1213 * <pre>
@@ -29,85 +30,57 @@ public List<Node> findEquivalentSubtrees(Node root) {
2930 return null ;
3031 }
3132
32- // Build map { Node -> (Vocabulary of sub nodes)}
33- Map <Node , Set <Character >> node2Voc = new HashMap <>();
34- buildNodeVocabulary (root , node2Voc );
35-
36- // Build Node->nodeSize map
37- Map <Node , Integer > node2Size = new HashMap <>();
38- buildNode2Size (root , node2Size );
33+ // Fill `vocabulary` field of nodes
34+ buildNodeVocabulary (root );
3935
4036 // Build Set<Character> -> List<Node> map
4137 Map <Set <Character >, List <Node >> voc2Nodes = new HashMap <>();
42- node2Voc = node2Voc .entrySet ().stream ()
43- .collect (Collectors .toMap (
44- Map .Entry ::getKey ,
45- Map .Entry ::getValue
46- ));
4738
48- for (Node node : node2Voc .keySet ()) {
49- Set <Character > value = node2Voc .get (node );
39+ Deque <Node > queue = new ArrayDeque <>();
40+ queue .add (root );
41+ while (!queue .isEmpty ()) {
42+ var current = queue .poll ();
43+ if (current .left != null ) {
44+ queue .add (current .left );
45+ }
46+ if (current .right != null ) {
47+ queue .add (current .right );
48+ }
49+ Set <Character > vocabulary = current .vocabulary ;
5050
51- if (!voc2Nodes .containsKey (value )) {
52- voc2Nodes .put (value , new ArrayList <>());
51+ if (!voc2Nodes .containsKey (vocabulary )) {
52+ voc2Nodes .put (vocabulary , new ArrayList <>());
5353 }
54- voc2Nodes .get (value ).add (node );
54+ voc2Nodes .get (vocabulary ).add (current );
5555 }
5656
5757 // Found equivalent nodes
58- voc2Nodes = voc2Nodes .entrySet ().stream ()
59- .filter (entry -> entry .getValue ().size () >= 2 )
60- .collect (Collectors .toMap (
61- Map .Entry ::getKey ,
62- entry -> entry .getValue ().stream ()
63- .sorted ((o1 , o2 ) -> node2Size .get (o2 ) - node2Size .get (o1 ))
58+ return voc2Nodes .values ().stream ()
59+ .filter (entry -> entry .size () >= 2 )
60+ .map (
61+ entry -> entry .stream ()
62+ .sorted ((o1 , o2 ) -> o2 .vocabulary .size () - o1 .vocabulary .size ())
6463 .limit (2 )
6564 .toList ()
66- ));
67- // Only absent sets with at least 2 related nodes remain
68-
69- if (voc2Nodes .isEmpty ()) {
70- return null ;
71- }
72-
73- Map <Set <Character >, List <Node >> map = voc2Nodes .entrySet ().stream ()
74- .sorted ((o1 , o2 ) -> o2 .getValue ().stream ().mapToInt (node2Size ::get ).sum () - o1 .getValue ().stream ().mapToInt (node2Size ::get ).sum ())
65+ )
66+ .sorted ((o1 , o2 ) -> o2 .stream ().mapToInt (nodeToIntFunction ()).sum () - o1 .stream ().mapToInt (nodeToIntFunction ()).sum ())
7567 .limit (1 )
76- .collect (Collectors .toMap (
77- Map .Entry ::getKey ,
78- Map .Entry ::getValue
79- ));
80-
81- return map .values ().iterator ().next ();
68+ .findFirst ().orElse (null );
8269 }
8370
84- private Set <Character > buildNodeVocabulary (Node node , Map <Node , Set <Character >> node2Voc ) {
85- if (!node2Voc .containsKey (node )) {
86- node2Voc .put (node , new HashSet <>());
87- }
88- if (node .left != null ) {
89- node2Voc .get (node ).add (node .left .value );
90- node2Voc .get (node ).addAll (buildNodeVocabulary (node .left , node2Voc ));
91- }
92- if (node .right != null ) {
93- node2Voc .get (node ).add (node .right .value );
94- node2Voc .get (node ).addAll (buildNodeVocabulary (node .right , node2Voc ));
95- }
96- return node2Voc .get (node );
71+ private static ToIntFunction <Node > nodeToIntFunction () {
72+ return node -> node .vocabulary .size ();
9773 }
9874
99- private int buildNode2Size (Node node , Map <Node , Integer > node2Size ) {
100- if (!node2Size .containsKey (node )) {
101- node2Size .put (node , 0 );
102- }
75+ private Set <Character > buildNodeVocabulary (Node node ) {
10376 if (node .left != null ) {
104- node2Size . put ( node , node2Size . get (node ) + 1 );
105- node2Size . put ( node , node2Size . get ( node ) + buildNode2Size (node .left , node2Size ));
77+ node . vocabulary . add (node . left . value );
78+ node . vocabulary . addAll ( buildNodeVocabulary (node .left ));
10679 }
10780 if (node .right != null ) {
108- node2Size . put ( node , node2Size . get (node ) + 1 );
109- node2Size . put ( node , node2Size . get ( node ) + buildNode2Size (node .right , node2Size ));
81+ node . vocabulary . add (node . right . value );
82+ node . vocabulary . addAll ( buildNodeVocabulary (node .right ));
11083 }
111- return node2Size . get ( node ) ;
84+ return node . vocabulary ;
11285 }
11386}
0 commit comments