1
1
class 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 ;
10
4
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 <>();
18
7
}
19
8
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 );
21
12
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
+ }
25
16
26
- emailsForAcc .putIfAbsent (parent , new HashSet <>());
27
- emailsForAcc .get (parent ).addAll (emails .subList (1 , emails .size ()));
17
+ return parent .get (x );
28
18
}
29
19
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 );
31
23
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
+ }
38
27
}
39
-
40
- return result ;
41
28
}
42
29
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 ();
45
33
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 );
48
37
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 );
51
42
}
52
43
}
53
44
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 );
60
49
}
61
50
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 );
68
58
}
59
+
60
+ return result ;
69
61
}
70
- }
62
+ }
0 commit comments