LeetCode-并查集
面试题 17.07. 婴儿名字
每年,政府都会公布一万个最常见的婴儿名字和它们出现的频率,也就是同名婴儿的数量。有些名字有多种拼法,例如,John 和 Jon 本质上是相同的名字,但被当成了两个名字公布出来。给定两个列表,一个是名字及对应的频率,另一个是本质相同的名字对。设计一个算法打印出每个真实名字的实际频率。注意,如果 John 和 Jon 是相同的,并且 Jon 和 Johnny 相同,则 John 与 Johnny 也相同,即它们有传递和对称性。
在结果列表中,选择 字典序最小 的名字作为真实名字。
示例:
输入:names = [“John(15)”,“Jon(12)”,“Chris(13)”,“Kris(4)”,“Christopher(19)”], synonyms = ["(Jon,John)","(John,Johnny)","(Chris,Kris)","(Chris,Christopher)"]
输出:[“John(27)”,“Chris(36)”]
提示:
names.length <= 100000
public String[] trulyMostPopular(String[] names, String[] synonyms) {
Map<String, Integer> nameMap = new HashMap<>();
for (String name : names) {
String[] arrs = name.split("\\(");
int times = Integer.parseInt(arrs[1].substring(0, arrs[1].length() - 1));
nameMap.put(arrs[0], times);
}
Union union = new Union(nameMap.keySet().toArray(new String[0]));
for (String name : synonyms) {
String[] arr = name.split(",");
String nameKey = arr[0].substring(1, arr[0].length());
String nameVal = arr[1].substring(0, arr[1].length() - 1);
union.union(nameKey, nameVal);
}
Map<String, Integer> resMap = new HashMap<>();
String pKey;
for (String key : nameMap.keySet()) {
pKey = union.find(key);
resMap.put(pKey, resMap.getOrDefault(pKey, 0)+nameMap.get(key));
}
String[] res = new String[resMap.size()];
int i = 0;
for (String key : resMap.keySet()) {
res[i] = key + "(" + resMap.get(key)+ ")";
i++;
}
return res;
}
class Union {
private Map<String, String> nameMap = new HashMap<>();
public Union(String[] names) {
for (String name : names) {
nameMap.put(name, name);
}
}
public String find(String key) {
if(!nameMap.containsKey(key)){
return key;
}
if (key.equals(nameMap.get(key))) {
return key;
} else {
return find(nameMap.get(key));
}
}
public void union(String key1, String key2) {
String p1 = find(key1);
String p2 = find(key2);
if (p1.compareTo(p2) > 0) {
nameMap.put(p1, p2);
} else {
nameMap.put(p2, p1);
}
}
}