classSolution{publicList<List<String>>accountsMerge(List<List<String>> accounts){int size = accounts.size();UnionFind uf =newUnionFind(accounts.size());HashMap<String,Integer> emailToAcc =newHashMap<>();// Iterate the accountsfor(int i =0; i < size;++i){List<String> details = accounts.get(i);// Iterate the emails under the accountfor(int j =1; j < details.size();++j){String email = details.get(j);// Find the emailif(emailToAcc.containsKey(email)){// Union the account because they're the same account
uf.union(i, emailToAcc.get(email));}else{
emailToAcc.put(email, i);}}}// Unique account -> emails of each accountHashMap<Integer,List<String>> accToEmails =newHashMap<>();for(String key : emailToAcc.keySet()){int root = uf.find(emailToAcc.get(key));if(!accToEmails.containsKey(root)){
accToEmails.put(root,newArrayList<String>());}// Add the email to the account
accToEmails.get(root).add(key);}// Collect the emails from accToEmailsList<List<String>> mergedDetails =newArrayList<>();for(Integer acc : accToEmails.keySet()){// Store the emailsList<String> emails = accToEmails.get(acc);// Sort the emailsCollections.sort(emails);// Insert the account name
emails.add(0, accounts.get(acc).get(0));
mergedDetails.add(emails);}return mergedDetails;}classUnionFind{int[] parent;int[] weight;publicUnionFind(int num){
parent =newint[num];
weight =newint[num];for(int i =0; i < num; i++){
parent[i]= i;
weight[i]=1;}}publicbooleanunion(int a,int b){int rootA =find(a);int rootB =find(b);// They are the same group alreadyif(rootA == rootB){returnfalse;}// Union// Weight of rootA is heavier than rootBif(weight[rootA]> weight[rootB]){// 小樹接到大樹
parent[rootB]= rootA;// 更新權重,rootA變成更大顆的樹了
weight[rootA]+= weight[rootB];}else{
parent[rootA]= rootB;
weight[rootB]+= weight[rootA];}returntrue;}// Find the rootpublicintfind(int a){while(a != parent[a]){// Path compression
parent[a]= parent[parent[a]];
a = parent[a];}return a;}}}