字符串并查集: 721. 账户合并 ( 并查集 )
解题思路:
首先通过哈希表建立并查集,哈希表的键值对都是字符串,然后将一个相连的并查集合并;
利用一个哈希表进行计数,计数的时候将值都累加到根元素。
最后进行输出,输出的时候从头遍历,如果当前元素是一个根元素,那就输出。
注意点:
1.在合并的时候,为了满足题意,将字典序小的根元素作为新的根元素。
AC Code
class Solution {
// fa[]
Map<String, String> map = new HashMap<>();
// findset根
public String findset(String x){
if(!map.get(x).equals(x)) {
map.put(x, findset(map.get(x)));
}
return map.get(x);
}
public void union(String x, String y) {
String rootx = findset(x);
String rooty = findset(y);
if(!rootx.equals(rooty)) {
// 连通
// 字典序小的做根节点 >> 稍微改变
if(rootx.compareTo(rooty) > 0) map.put(rootx, rooty);
else map.put(rooty, rootx);
}
}
public String[] trulyMostPopular(String[] names, String[] synonyms) {
Map<String, Integer> cnt = new HashMap<>();
// 初始化
for(String name : names) {
// 名字
int idx = name.indexOf("(");
String n = name.substring(0, idx);
map.put(n, n);
}
// synonyms 连通
for(String s : synonyms) {
int idx = s.indexOf(",");
// 两个名字
String a = s.substring(1, idx);
String b = s.substring(idx + 1, s.length() - 1);
// 初始化
if(!map.containsKey(a)) map.put(a, a);
if(!map.containsKey(b)) map.put(b, b);
// 连通
// 字典序小的做根节点
union(a, b);
}
// 同时将数量合并到 cnt 中
for(String name : names) {
// 名字
int idx = name.indexOf("(");
String n = name.substring(0, idx);
// 数量
int end = name.indexOf(")");
Integer count = Integer.parseInt(name.substring(idx + 1, end));
String root = findset(n);
// 在原来的基础上加
Integer begin = cnt.getOrDefault(root, 0);
cnt.put(root, count + begin);
}
// 结果
List<String> list = new ArrayList<>();
for(String name : names) {
// 名字
int idx = name.indexOf("(");
String n = name.substring(0, idx);
String root = findset(n);
// 只要根节点的
if(root.equals(n)) {
//
int count = cnt.get(root);
String data = root + "(" + count + ")";
list.add(data);
}
}
return list.toArray(new String[list.size()]);
}
}
参考: Java 并查集 通用做法