字符串分组
难度:
标签:
题目描述
代码结果
运行时间: 649 ms, 内存: 47.2 MB
import java.util.*;
import java.util.stream.*;
// 思路:使用并查集(Union-Find)结合Java Stream API来解决分组问题。首先初始化每个字符串的唯一ID,然后通过遍历字符串,将关联的字符串合并在同一个组中。最后统计每个组的大小,并找到最大的组大小。
public class Solution {
public int[] groupStrings(String[] words) {
int n = words.length;
UnionFind uf = new UnionFind(n);
Map<String, Integer> map = new HashMap<>();
IntStream.range(0, n).forEach(i -> {
char[] arr = words[i].toCharArray();
Arrays.sort(arr);
String sorted = new String(arr);
if (!map.containsKey(sorted)) {
map.put(sorted, i);
} else {
uf.union(i, map.get(sorted));
}
IntStream.range(0, arr.length).forEach(j -> {
char temp = arr[j];
arr[j] = '#'; // 替换一个字母
String modified = new String(arr);
if (map.containsKey(modified)) {
uf.union(i, map.get(modified));
}
arr[j] = temp; // 复原字母
});
});
int[] count = new int[n];
IntStream.range(0, n).forEach(i -> count[uf.find(i)]++);
int groups = (int) IntStream.of(count).filter(size -> size > 0).count();
int maxSize = IntStream.of(count).max().orElse(0);
return new int[]{groups, maxSize};
}
class UnionFind {
int[] parent, rank;
public UnionFind(int n) {
parent = new int[n];
rank = new int[n];
IntStream.range(0, n).forEach(i -> parent[i] = i);
}
public int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]);
}
return parent[x];
}
public void union(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX != rootY) {
if (rank[rootX] > rank[rootY]) {
parent[rootY] = rootX;
} else if (rank[rootX] < rank[rootY]) {
parent[rootX] = rootY;
} else {
parent[rootY] = rootX;
rank[rootX]++;
}
}
}
}
}
解释
方法:
这个题解使用了位掩码和并查集来将具有一定关联的字符串分组。首先,每个字符串被转换成一个整数位掩码,其中位掩码的第 i 位表示字符 'a'+i 是否出现在字符串中。这使得比较两个字符串是否只有一个字符的差异变得容易和快速。题解中先将字符串按长度排序,以便尽可能地减少比较次数。然后,使用一个字典来记录已经遇到的位掩码及其对应字符串的索引。对于每个位掩码,我们不仅记录它本身,还生成26个可能的通过增加或删除单个字母得到的位掩码,并尝试将当前字符串与这些位掩码所代表的字符串联合。这样可以确保所有只差一个字符的字符串都会被放入同一个组。最后,使用并查集来确定组成员,并统计最大组的大小。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
在使用位掩码表示字符串时,为什么只考虑字符是否出现,而不是字符出现的次数?
▷🦆
如何确保通过增加、删除或替换一个字母得到的位掩码都能正确地反映两个字符串之间的关系?
▷🦆
题解中提到按字符串长度排序可以减少比较次数,请问这是基于什么原理?会不会有例外情况导致效果不显著?
▷🦆
并查集在此题解中如何处理字符串分组,特别是如何确保一个组内的任一字符串与其他组的字符串都不关联?
▷