Question:

Solution:

For Disjoint Set class copy template from UNION BY RANK (LESS INTUITIVE).

public List<List<String>> accountsMerge(List<List<String>> accounts) {
        int n = accounts.size();
        DisjointSet dsu = new DisjointSet(n);
 
        // Step 1: Create a mapping from email to user index
        Map<String, Integer> emailToIndex = new HashMap<>();
        for (int i = 0; i < n; i++) {
            List<String> account = accounts.get(i);
            for (int j = 1; j < account.size(); j++) {
                String email = account.get(j);
                if (!emailToIndex.containsKey(email)) {
                    emailToIndex.put(email, i);
                } else {
                    // Step 2: Merge accounts with the same email
                    dsu.unionByRank(i, emailToIndex.get(email));
                }
            }
        }
 
        // Step 3: Create a mapping from [user index] to [list] of emails
        Map<Integer, List<String>> indexToEmails = new HashMap<>();
        for (Map.Entry<String, Integer> entry : emailToIndex.entrySet()) {
            String email = entry.getKey();
            int index = dsu.findUltimateParent(entry.getValue());
 
            indexToEmails.putIfAbsent(index, new ArrayList<>());//initialize the index with empty array
            indexToEmails.get(index).add(email); //get that array and add email to that list
        }
 
        // Step 4: Create the merged accounts list
        List<List<String>> mergedAccounts = new ArrayList<>();
        for (Map.Entry<Integer, List<String>> entry : indexToEmails.entrySet()) {
            int userIndex = entry.getKey();
            List<String> emails = entry.getValue();
            
            Collections.sort(emails);
            
            List<String> account = new ArrayList<>();
            account.add(accounts.get(userIndex).get(0)); // Add the account name
            account.addAll(emails);
            mergedAccounts.add(account);
        }
 
        return mergedAccounts;
    }