這個題解法感覺對圖的理解很深刻。一開始先不管name, 只處理emails. 把出現(xiàn)在同一個account里面的email都跟該account的第一個email連接较锡,連接的含義是雙向的,就是說把彼此存入到自己的neighbors中次泽,本解法里就是map里對應(yīng)的HashSet<Strings>. 然后用一個visited來保存訪問過的email. 遍歷account, 每次取出第一個email, 先檢查是不是visited, 因為它可能在別的account里不是第一個email而被訪問過,如果是的話我們繼續(xù)訪問就會出現(xiàn)重復(fù)結(jié)果裁僧,因為email最后都會被merge到一個賬號渤早。如果沒有訪問過卤材,我們就要做一個bfs, 從該email出發(fā),找它的所有鄰居竣况,加到list里克婶。最后要記得sort所有的emails.最后的最后才把名字加到最前面,構(gòu)成一組答案。為什么從account的第一個email出發(fā)做BFS可以找到所有圖中于這個email相連的emails呢情萤?因為在該account中不用說鸭蛙,我們建圖的時候就連接了所有的emails to 第一個email,那么我們寬搜很快就能得到這些同一個account的email. 同時筋岛,這個email可能出現(xiàn)在其他account的非首個email的位置上娶视,而我們建圖的時候,連接了它跟這個account的首個email睁宰,那么我們把這個首個email放進(jìn)queue里面之后肪获,一定能訪問到所有跟它連接的在該account里的emails, 所以這個account里的所有emails也可以訪問到。因此我們從這個account的第一個email出發(fā)做寬搜柒傻,一定是找得到所有跟它相連的emails的孝赫。
class Solution {
public List<List<String>> accountsMerge(List<List<String>> accounts) {
List<List<String>> res = new ArrayList<>();
Map<String, Set<String>> map = new HashMap<>();
for (List<String> account : accounts){
for (int i = 1; i < account.size(); i++){
if (!map.containsKey(account.get(i))){
map.put(account.get(i), new HashSet<String>());
}
map.get(account.get(i)).add(account.get(1));
map.get(account.get(1)).add(account.get(i));
}
}
Set<String> visited = new HashSet<>();
for (List<String> account : accounts){
if (!visited.contains(account.get(1))){
List<String> list = new ArrayList<>();
bfs(map, account.get(1), visited, list);
Collections.sort(list);
list.add(0, account.get(0));
res.add(list);
}
}
return res;
}
private void bfs(Map<String, Set<String>> map, String s, Set<String> visited, List<String> list){
Queue<String> queue = new LinkedList<>();
queue.offer(s);
visited.add(s);
while (!queue.isEmpty()){
String curt = queue.poll();
list.add(curt);
for (String nei : map.get(curt)){
if (!visited.contains(nei)){
queue.offer(nei);
visited.add(nei);
}
}
}
}
}