11class Solution {
2- public List <List <String >> accountsMerge (List <List <String >> accounts ) {
3- UnionFind uf = new UnionFind (accounts .size ());
4-
5- Map <String , Integer > emailToAcc = new HashMap <>();
6-
7- for (int i = 0 ; i < accounts .size (); i ++) {
8- for (int j = 1 ; j < accounts .get (i ).size (); j ++) {
9- String email = accounts .get (i ).get (j );
2+ private class UnionFind {
3+ private Map <String , String > parent ;
104
11- if (emailToAcc .containsKey (email )) {
12- int prevParent = emailToAcc .get (email );
13- uf .union (prevParent , i );
14- } else {
15- emailToAcc .put (email , i );
16- }
17- }
5+ public UnionFind () {
6+ parent = new HashMap <>();
187 }
198
20- Map <Integer , Set <String >> emailsForAcc = new HashMap <>();
9+ public String find (String x ) {
10+ // Upon adding a new item, its parent is itself
11+ parent .putIfAbsent (x , x );
2112
22- for ( int i = 0 ; i < accounts . size (); i ++ ) {
23- int parent = uf . find (i );
24- List < String > emails = accounts . get ( i );
13+ if (! parent . get ( x ). equals ( x ) ) {
14+ parent . put ( x , find (parent . get ( x ))); // Path compression; directly specify the parent via recursion
15+ }
2516
26- emailsForAcc .putIfAbsent (parent , new HashSet <>());
27- emailsForAcc .get (parent ).addAll (emails .subList (1 , emails .size ()));
17+ return parent .get (x );
2818 }
2919
30- List <List <String >> result = new ArrayList <>();
20+ public void union (String x , String y ) {
21+ String rootX = find (x );
22+ String rootY = find (y );
3123
32- for (int key : emailsForAcc .keySet ()) {
33- List <String > temp = new ArrayList <>();
34- temp .addAll (emailsForAcc .get (key ));
35- Collections .sort (temp );
36- temp .add (0 , accounts .get (key ).get (0 ));
37- result .add (temp );
24+ if (!rootX .equals (rootY )) {
25+ parent .put (rootX , rootY );
26+ }
3827 }
39-
40- return result ;
4128 }
4229
43- private class UnionFind {
44- private int [] parents ;
30+ public List <List <String >> accountsMerge (List <List <String >> accounts ) {
31+ Map <String , String > emailToName = new HashMap <>();
32+ UnionFind uf = new UnionFind ();
4533
46- public UnionFind (int n ) {
47- parents = new int [n ];
34+ for (List <String > account : accounts ) {
35+ String name = account .get (0 );
36+ String initialEmail = account .get (1 );
4837
49- for (int i = 0 ; i < parents .length ; i ++) {
50- parents [i ] = i ;
38+ for (int i = 1 ; i < account .size (); i ++) {
39+ String email = account .get (i );
40+ emailToName .putIfAbsent (email , name );
41+ uf .union (initialEmail , email );
5142 }
5243 }
5344
54- public int find (int node ) {
55- if (parents [node ] == node ) {
56- return node ;
57- }
58- parents [node ] = find (parents [parents [node ]]);
59- return parents [node ];
45+ Map <String , TreeSet <String >> unions = new HashMap <>();
46+ for (String email : emailToName .keySet ()) {
47+ String root = uf .find (email );
48+ unions .computeIfAbsent (root , x -> new TreeSet <>()).add (email );
6049 }
6150
62- public void union (int i , int j ) {
63- int p1 = find (i ), p2 = find (j );
64- if (p1 == p2 ) {
65- return ;
66- }
67- parents [p2 ] = p1 ;
51+ List <List <String >> result = new ArrayList <>();
52+
53+ for (Map .Entry <String , TreeSet <String >> entry : unions .entrySet ()) {
54+ List <String > temp = new ArrayList <>();
55+ temp .add (emailToName .get (entry .getKey ()));
56+ temp .addAll (entry .getValue ());
57+ result .add (temp );
6858 }
59+
60+ return result ;
6961 }
70- }
62+ }
0 commit comments