Bird
Raised Fist0
Interview Prepunion-findmediumFacebookAmazonGoogle

Accounts Merge

Choose your preparation mode4 modes available
</>
IDE
def accountsMerge(accounts: list[list[str]]) -> list[list[str]]:public List<List<String>> accountsMerge(List<List<String>> accounts)vector<vector<string>> accountsMerge(vector<vector<string>>& accounts)function accountsMerge(accounts)
def accountsMerge(accounts: list[list[str]]) -> list[list[str]]:
    # Write your solution here
    pass
class Solution {
    public List<List<String>> accountsMerge(List<List<String>> accounts) {
        // Write your solution here
        return new ArrayList<>();
    }
}
#include <vector>
#include <string>
using namespace std;

vector<vector<string>> accountsMerge(vector<vector<string>>& accounts) {
    // Write your solution here
    return {};
}
function accountsMerge(accounts) {
    // Write your solution here
}
Coming soon
0/10
Common Bugs to Avoid
Wrong: [["John", "johnsmith@mail.com"], ["John", "john00@mail.com"]]Failing to merge accounts sharing emails; treating accounts independently.✅ Implement union-find on emails to merge connected accounts before output.
Wrong: [["Anna", "a@mail.com", "b@mail.com", "c@mail.com"]]Merging accounts based on name only, ignoring email overlap.✅ Merge accounts only if they share at least one email, not just by name.
Wrong: [["X", "x@mail.com"], ["Y", "y@mail.com"], ["Z", "z@mail.com"]]Failing to merge accounts connected by email cycles or chains.✅ Use union-find with path compression to merge all connected emails.
Wrong: [["A", "a@mail.com"], ["B", "b@mail.com"], ["C", "c@mail.com"]]Incorrectly merging accounts with unique emails or failing to sort emails.✅ Only merge accounts with shared emails and sort emails in output.
Wrong: Solution times out on large inputs due to nested loops checking all pairs.✅ Optimize to union-find with email to account mapping to achieve near-linear time.
✓
Test Cases
t1_01basic
Input[["John","johnsmith@mail.com","john00@mail.com"],["John","johnnybravo@mail.com"],["John","johnsmith@mail.com","john_newyork@mail.com"],["Mary","mary@mail.com"]]
Expected[["John","john00@mail.com","john_newyork@mail.com","johnsmith@mail.com"],["John","johnnybravo@mail.com"],["Mary","mary@mail.com"]]

The first and third accounts share 'johnsmith@mail.com', so they are merged. The second and fourth accounts have unique emails and remain separate.

t1_02basic
Input[["Alice","alice@mail.com","alice2@mail.com"],["Bob","bob@mail.com"],["Alice","alice2@mail.com","alice3@mail.com"],["Charlie","charlie@mail.com"]]
Expected[["Alice","alice@mail.com","alice2@mail.com","alice3@mail.com"],["Bob","bob@mail.com"],["Charlie","charlie@mail.com"]]

Accounts 1 and 3 share 'alice2@mail.com' so they merge; others remain separate.

t2_01edge
Input[]
Expected[]

Empty input should return empty output.

t2_02edge
Input[["Solo","solo@mail.com"]]
Expected[["Solo","solo@mail.com"]]

Single account with one email should return itself.

t2_03edge
Input[["A","a@mail.com"],["B","b@mail.com"],["C","c@mail.com"]]
Expected[["A","a@mail.com"],["B","b@mail.com"],["C","c@mail.com"]]

All accounts have unique emails; no merges; output emails sorted.

t2_04edge
Input[["Same","same@mail.com"],["Same","same@mail.com"],["Same","same@mail.com"]]
Expected[["Same","same@mail.com"]]

All accounts share the same email, so they merge into one account.

t3_01corner
Input[["X","x@mail.com","y@mail.com"],["Y","y@mail.com","z@mail.com"],["Z","z@mail.com","x@mail.com"]]
Expected[["X","x@mail.com","y@mail.com","z@mail.com"]]

All accounts share emails forming a cycle; all merge into one account.

t3_02corner
Input[["Anna","a@mail.com"],["Anna","b@mail.com"],["Anna","c@mail.com"]]
Expected[["Anna","a@mail.com"],["Anna","b@mail.com"],["Anna","c@mail.com"]]

Multiple accounts with same name but no shared emails remain separate.

t3_03corner
Input[["D","d1@mail.com","d2@mail.com"],["E","d2@mail.com","e1@mail.com"],["F","e1@mail.com","f1@mail.com"],["G","g1@mail.com"]]
Expected[["D","d1@mail.com","d2@mail.com","e1@mail.com","f1@mail.com"],["G","g1@mail.com"]]

Chain of shared emails merges first three accounts; last account remains separate.

t4_01performance
Input{"_description":"n=100000 at constraint boundary - executor generates this input with unique and some shared emails"}
⏱ Performance - must finish in 2000ms

Test with 100000 accounts and up to 1000 emails each to verify O(N*M*α(N*M)) union-find solution runs within 2 seconds.

Practice

(1/5)
1. You are given a list of edges representing an undirected graph with n nodes. The graph started as a tree with n nodes and one additional edge was added, creating a cycle. Which algorithmic approach guarantees finding the edge that creates the cycle efficiently?
easy
A. Union-Find (Disjoint Set Union) with path compression and union by rank to detect cycles during edge insertion
B. Dynamic programming to store reachable nodes and detect cycles
C. Depth-first search (DFS) cycle detection on each edge, checking connectivity repeatedly
D. Greedy algorithm that removes edges with the highest node degree first

Solution

  1. Step 1: Understand problem constraints

    The graph is initially a tree with n nodes, so it has exactly n-1 edges. Adding one edge creates exactly one cycle.
  2. Step 2: Identify suitable algorithm

    Union-Find efficiently tracks connected components and detects if adding an edge connects two nodes already in the same component, indicating a cycle.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Union-Find detects cycles in near-linear time [OK]
Hint: Union-Find detects cycles during edge insertion [OK]
Common Mistakes:
  • Thinking DFS on each edge is efficient enough
  • Believing DP can track cycles here
  • Assuming greedy edge removal finds cycles
2. Identify the bug in the following union-find code snippet used to solve the Most Stones Removed with Same Row or Column problem:
class UnionFind:
    def __init__(self):
        self.parent = {}
        self.rank = {}
        self.count = 0

    def find(self, x):
        if x not in self.parent:
            self.parent[x] = x
            self.rank[x] = 0
            self.count += 1
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]

    def union(self, x, y):
        rootX = self.find(x)
        rootY = self.find(y)
        if rootX != rootY:
            if self.rank[rootX] < self.rank[rootY]:
                self.parent[rootX] = rootY
            elif self.rank[rootX] > self.rank[rootY]:
                self.parent[rootY] = rootX
            else:
                self.parent[rootY] = rootX
                self.rank[rootX] += 1
            # BUG: missing decrement of count here

uf = UnionFind()
for x, y in stones:
    uf.union(x, ~y)

return len(stones) - uf.count
medium
A. Line where rank is incremented after union
B. Line where parent is assigned in find method
C. Line where new nodes are initialized in find
D. Line missing decrement of count after union

Solution

  1. Step 1: Understand count variable role

    Count tracks number of connected components, incremented on new node creation.
  2. Step 2: Identify missing update

    After union merges two components, count must decrement but code misses this step.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Without decrement, count overestimates components -> wrong answer [OK]
Hint: Count must decrease on union of distinct sets [OK]
Common Mistakes:
  • Forgetting to decrement count after union
  • Incorrect rank updates
  • Misusing parent assignments in find
3. The following code attempts to find a redundant connection using union-find but contains a subtle bug. Identify the line causing incorrect behavior.
medium
A. Line setting parent[i] = i in the for loop
B. Line incrementing rank[rootA] after union
C. Line checking if rootA == rootB in union function
D. Line initializing parent with zeros: parent = [0]*(n+1)

Solution

  1. Step 1: Analyze parent array initialization

    Initializing parent with zeros causes all nodes to initially point to 0, which is incorrect for 1-based nodes.
  2. Step 2: Check for correct parent assignment

    The for loop tries to fix this, but if n=0, loop may not run properly or indexing may be off; better to initialize parent as list(range(n+1)) directly.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Incorrect parent initialization leads to wrong find results [OK]
Hint: Parent array must be initialized to self indices [OK]
Common Mistakes:
  • Forgetting to initialize parent properly
  • Assuming zeros are valid parents
  • Misindexing parent array
4. What is the time complexity of the optimal union-find + priority queue approach to the smallest string with swaps problem, where n is the length of the string and m is the number of pairs?
medium
A. O(n log n + m α(n)) where α(n) is the inverse Ackermann function from union-find operations
B. O(n * m) due to iterating over all pairs for each character
C. O(n²) because sorting characters in each connected component can be quadratic in worst case
D. O(m log n) because union-find operations dominate the runtime

Solution

  1. Step 1: Analyze union-find operations

    Union-find performs m union/find operations in O(m α(n)) time, where α(n) is very slow growing and almost constant.
  2. Step 2: Analyze sorting step

    Sorting characters in all connected components combined takes O(n log n) time.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Union-find plus sorting dominates runtime as O(n log n + m α(n)) [OK]
Hint: Union-find nearly linear; sorting dominates with n log n [OK]
Common Mistakes:
  • Assuming O(n*m) due to nested loops
  • Confusing sorting cost as O(n²)
  • Ignoring inverse Ackermann factor
5. Suppose the problem is modified so that edges can be reused multiple times (i.e., multi-edges allowed), and we want to remove the maximum number of edges while keeping the graph traversable for both Alice and Bob. Which modification to the optimal union-find approach is necessary?
hard
A. Use a multigraph union-find variant that counts edge multiplicities and only removes redundant edges after full connectivity.
B. Switch to a shortest path algorithm since union-find cannot handle multi-edges.
C. No change needed; the original union-find approach works as is.
D. Process edges in arbitrary order without sorting since multi-edges guarantee connectivity.

Solution

  1. Step 1: Understand multi-edge impact

    Multi-edges mean multiple edges connect same nodes; union-find alone merges sets once, ignoring multiplicity.
  2. Step 2: Modify union-find approach

    Need to track edge counts per connection and only remove edges that do not break connectivity, requiring a multigraph-aware union-find or additional bookkeeping.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Original union-find ignores multiplicity -> must track edge counts [OK]
Hint: Union-find merges sets once; multi-edges require counting edges [OK]
Common Mistakes:
  • Assuming union-find handles multi-edges without change
  • Ignoring edge multiplicity
  • Switching to unrelated algorithms unnecessarily
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard