相似字符串组
难度:
标签:
题目描述
代码结果
运行时间: 158 ms, 内存: 16.5 MB
/*
* 思路:
* 1. 使用流 (Stream) 的方式来简化代码,尤其是在判断相似性和组的合并过程中。
* 2. 使用并查集(Union-Find)来管理相似组。
* 3. 最后统计不同的组数。
*/
import java.util.stream.IntStream;
class Solution {
private int find(int[] parent, int i) {
if (parent[i] != i) {
parent[i] = find(parent, parent[i]);
}
return parent[i];
}
private void union(int[] parent, int[] rank, int i, int j) {
int rootI = find(parent, i);
int rootJ = find(parent, j);
if (rootI != rootJ) {
if (rank[rootI] > rank[rootJ]) {
parent[rootJ] = rootI;
} else if (rank[rootI] < rank[rootJ]) {
parent[rootI] = rootJ;
} else {
parent[rootJ] = rootI;
rank[rootI]++;
}
}
}
private boolean areSimilar(String a, String b) {
return IntStream.range(0, a.length())
.filter(i -> a.charAt(i) != b.charAt(i))
.count() <= 2;
}
public int numSimilarGroups(String[] strs) {
int n = strs.length;
int[] parent = IntStream.range(0, n).toArray();
int[] rank = new int[n];
IntStream.range(0, n).forEach(i ->
IntStream.range(i + 1, n).filter(j -> areSimilar(strs[i], strs[j]))
.forEach(j -> union(parent, rank, i, j))
);
return (int) IntStream.range(0, n).filter(i -> parent[i] == i).count();
}
}
解释
方法:
这个题解使用并查集来解决相似字符串分组的问题。主要思路是:
1. 先对输入的字符串数组去重。
2. 根据输入规模选择两种不同的算法:
- 当字符串数量n大于字符串长度平方m^2时,使用O(N*M^2)的算法
- 否则使用O(N^2*M)的算法
3. O(N^2*M)算法通过两两比较字符串的相似性,对相似的字符串进行并查集合并操作
4. O(N*M^2)算法先生成每个字符串的所有通配形式,建立通配串到原字符串的映射,同时记录字符串之间的相似关系,最后对有相似关系的字符串进行并查集合并
5. 最后对并查集的根节点去重并输出集合的大小,即为相似字符串组的数量
时间复杂度:
O(min(N^2*M, N*M^2))
空间复杂度:
O(N) ~ O(N*M^2)
代码细节讲解
🦆
在选择使用O(N^2*M)算法或O(N*M^2)算法的依据是什么?为什么当n大于m^2时选择使用O(N*M^2)算法?
▷🦆
在并查集中,如何处理并查集的路径压缩以优化查找效率?
▷🦆
题解中提到的`生成每个字符串的所有通配形式`具体是如何实现的?能否具体说明生成规则?
▷🦆
为什么相似判定函数`check`在发现两个字符串的不同字符位置超过2个时就返回False?
▷