Example 1:
Input: accounts = [[“John”,“johnsmith@mail.com”,“john_newyork@mail.com”],[“John”,“johnsmith@mail.com”,“john00@mail.com”],[“Mary”,“mary@mail.com”],[“John”,“johnnybravo@mail.com”]] Output: [[“John”,“john00@mail.com”,“john_newyork@mail.com”,“johnsmith@mail.com”],[“Mary”,“mary@mail.com”],[“John”,“johnnybravo@mail.com”]] Explanation: The first and second John’s are the same person as they have the common email “johnsmith@mail.com”. The third John and Mary are different people as none of their email addresses are used by other accounts. We could return these lists in any order, for example the answer [[‘Mary’, ‘mary@mail.com’], [‘John’, ‘johnnybravo@mail.com’], [‘John’, ‘john00@mail.com’, ‘john_newyork@mail.com’, ‘johnsmith@mail.com’]] would still be accepted.
public List<List<String>> accountsMerge(List<List<String>> accounts) {
Map<String, String> parentKeyMap = new HashMap<>();
Map<String, String> parentMap = new HashMap<>();
Map<String, String> link = new HashMap<>();
Map<String, TreeSet<String>> result = new HashMap<>();
// parent is assigned to parent
int key=0;
for(List<String> row : accounts){
String parent = row.get(0);
parentMap.put(String.valueOf(key), String.valueOf(key));
parentKeyMap.put( String.valueOf(key), parent);
// decide link
for(int i=1; i< row.size() ; i++){
if( link.get(row.get(i)) == null ){
link.put(row.get(i), String.valueOf(key));
}else{
String parentDestination = link.get(row.get(i));
parentMap.put(String.valueOf(key), parentDestination);
}
}
key++;
}
// create final result
for(String val : link.keySet()){
String l = findParent(parentMap,link, val);
if(result.get(l) == null) {
result.put(l, new TreeSet<>());
}
result.get(l).add(val);
}
// convert map to List<List<String>>
List<List<String>> result2 = new ArrayList<>();
for(String val : result.keySet()){
List<String> arr = new ArrayList<>(result.get(val));
arr.add(0, parentKeyMap.get(val));
result2.add(arr);
}
return result2;
}
public String findParent(Map<String, String> parentMap,Map<String, String> link, String current) {
String newCurrent = link.get(current);
while(true){
if(!parentMap.get(newCurrent).equals(newCurrent)){
newCurrent = parentMap.get(newCurrent);
}else{
return parentMap.get(newCurrent);
}
}
}