Accounts Merge
Clarify the problem:
- The problem requires us to merge accounts with the same email addresses and return a list of merged accounts.
- Each account is represented by a list of strings, where the first element is the name of the account owner, and the following elements are email addresses associated with that account.
- We need to group accounts with the same email addresses and merge them into a single account while preserving the original order of the accounts.
Analyze the problem:
- Input: A list of lists representing accounts, where each account contains a name and email addresses.
- Output: A list of lists representing merged accounts.
- Constraints:
- The length of the accounts list is between 1 and 10^4.
- The length of each account is between 1 and 10.
- The email addresses are lowercase alphanumeric characters.
- The number of email addresses can be different for each account.
Design an algorithm:
- We can solve this problem using the Union-Find algorithm.
- We need to build a graph where each email address is a node, and an edge exists between two nodes if they belong to the same account.
- We iterate through the accounts and add each email address to the graph, creating an edge between the email addresses of the same account.
- After constructing the graph, we perform a depth-first search (DFS) starting from each email address to find all connected email addresses.
- We group the connected email addresses and add them to the result list as merged accounts.
- To optimize the process, we can use a hashmap to map each email address to its corresponding account owner.
- Finally, we return the list of merged accounts.
Explain your approach:
- We will implement the Union-Find algorithm to merge accounts with the same email addresses.
- We create a hashmap to map each email address to its corresponding account owner.
- We create a graph using a dictionary, where each email address is a key, and its value is a set of connected email addresses.
- We iterate through the accounts and add each email address to the graph, creating an edge between the email addresses of the same account.
- After constructing the graph, we perform a depth-first search (DFS) starting from each email address to find all connected email addresses.
- We group the connected email addresses and add them to the result list as merged accounts, appending the account owner's name at the beginning.
- Finally, we return the list of merged accounts.
Write clean and readable code:
pythondef accountsMerge(accounts): def find(parent, i): if parent[i] != i: parent[i] = find(parent, parent[i]) return parent[i] def union(parent, rank, i, j): root_i = find(parent, i) root_j = find(parent, j) if rank[root_i] < rank[root_j]: parent[root_i] = root_j elif rank[root_i] > rank[root_j]: parent[root_j] = root_i else: parent[root_j] = root_i rank[root_i] += 1 email_to_name = {} email_to_id = {} id_counter = 0 for account in accounts: name = account[0] emails = account[1:] for email in emails: if email not in email_to_id: email_to_id[email] = id_counter id_counter += 1 email_to_name[email] = name parent = [i for i in range(id_counter)] rank = [0] * id_counter for account in accounts: emails = account[1:] root = find(parent, email_to_id[emails[0]]) for email in emails[1:]: union(parent, rank, root, email_to_id[email]) merged_accounts = {} for email, id in email_to_id.items(): root = find(parent, id) if root in merged_accounts: merged_accounts[root].append(email) else: merged_accounts[root] = [email] merged_results = [] for emails in merged_accounts.values(): name = email_to_name[emails[0]] merged_results.append([name] + sorted(emails)) return merged_results
Test your code:
python# Example 1 accounts = [ ["John", "johnsmith@mail.com", "john00@mail.com"], ["John", "johnnybravo@mail.com"], ["John", "johnsmith@mail.com", "john_newyork@mail.com"], ["Mary", "mary@mail.com"] ] print(accountsMerge(accounts)) # Output: [ # ["John","john00@mail.com","john_newyork@mail.com","johnsmith@mail.com"], # ["John","johnnybravo@mail.com"], # ["Mary","mary@mail.com"] # ] # Example 2 accounts = [ ["Gabe", "gabe@mail.com", "gabriel@mail.com"], ["Gabe", "gabriel@mail.com", "gabriel1@mail.com"], ["Gabe", "gabriel1@mail.com", "gabriel2@mail.com"] ] print(accountsMerge(accounts)) # Output: [["Gabe","gabriel1@mail.com","gabriel2@mail.com","gabriel@mail.com","gabe@mail.com"]] # Additional Test Case accounts = [ ["Alice", "alice@mail.com"], ["Bob", "bob@mail.com"], ["Charlie", "charlie@mail.com"], ] print(accountsMerge(accounts)) # Output: [["Alice","alice@mail.com"],["Bob","bob@mail.com"],["Charlie","charlie@mail.com"]]
Optimize if necessary:
- The solution has a time complexity of O(n * log(m)), where n is the number of accounts and m is the total number of email addresses.
- The time complexity is dominated by the Union-Find operations, which have a logarithmic time complexity.
- The space complexity is O(n * m) due to the hashmap and graph representation.
Handle error cases:
- There are no specific error cases to handle for this problem.
- The problem guarantees that the accounts list will have at least one account, and each account will have at least one email address.
Discuss complexity analysis:
- The time complexity of the solution is O(n * log(m)), where n is the number of accounts and m is the total number of email addresses.
- The space complexity is O(n * m) due to the hashmap and graph representation.
- The solution is efficient for the given constraints and provides the correct output.