This problem requires merging accounts that share common emails. The key is to use
Union-Find (Disjoint Set Union)
to efficiently group connected emails. First, we
initialize each email as its own parent.
Then, we
union emails
from the same
account.
After grouping, we
collect all emails under
their root parent
and
format the results.
The
path compression in
the
'find' operation
ensures optimal performance.
class Solution { // This find is using path compression // With path compression, instead of following the chain every time, // we make each email directly point to the root when we find it. // This way, next time it's an instant lookup. public String find(String email, Map<String,String> parentMap){ if(!parentMap.get(email).equals(email)){ // parentMap.put(email,find(parentMap.get(email),parentMap)); email = find(parentMap.get(email),parentMap); } return email; // return parentMap.get(email); } public List<List<String>> accountsMerge(List<List<String>> accounts) { Map<String,String> mailToPerson = new HashMap<>(); Map<String,String> parentMap = new HashMap<>(); Map<String,TreeSet<String>> parentToEmails = new HashMap<>(); // First email to All of its child // Initialization for(List<String> entity : accounts){ for(int i=1;i<entity.size();i++){ mailToPerson.put(entity.get(i),entity.get(0)); // Email to Name of Person parentMap.put(entity.get(i),entity.get(i)); // Every email is parent of itself } } // Assign Parents for(List<String> entity : accounts){ String parentOfFirstEmail = find(entity.get(1),parentMap); for(int i=2;i<entity.size();i++){ String parentOfChildEmail = find(entity.get(i),parentMap); parentMap.put(parentOfChildEmail,parentOfFirstEmail); } } // Construct the ans in Mail --> All Child Mails ( including Parent mail) for(List<String> entity : accounts){ String parentOfFirstemail = find(entity.get(1),parentMap); for(int i=1;i<entity.size();i++){ parentToEmails.putIfAbsent(parentOfFirstemail,new TreeSet<>()); parentToEmails.get(parentOfFirstemail).add(entity.get(i)); } } // Store Answer as asked in the question List<List<String>> ans = new ArrayList<>(); for(String entity : parentToEmails.keySet()){ List<String> list = new ArrayList<>(parentToEmails.get(entity)); // All childs corresponding to first email list.add(0,mailToPerson.get(entity)); // Add person name on top index ans.add(list); } return ans; } }
Where n is the total number of emails and α is the inverse Ackermann function (nearly constant time due to path compression).
We use O(n) space to store parent relationships, email mappings, and the final result.