题目:
如果交换字符串 X 中的两个不同位置的字母,使得它和字符串 Y 相等,那么称 X 和 Y 两个字符串相似。如果这两个字符串本身是相等的,那它们也是相似的。
例如,“tars” 和 “rats” 是相似的 (交换 0 与 2 的位置); “rats” 和 “arts” 也是相似的,但是 “star” 不与 “tars”,“rats”,或 “arts” 相似。
总之,它们通过相似性形成了两个关联组:{“tars”, “rats”, “arts”} 和 {“star”}。注意,“tars” 和 “arts” 是在同一组中,即使它们并不相似。形式上,对每个组而言,要确定一个单词在组中,只需要这个词和该组中至少一个单词相似。
给你一个字符串列表 strs。列表中的每个字符串都是 strs 中其它所有字符串的一个字母异位词。请问 strs 中有多少个相似字符串组?
题解:
很简单的思路,就是一个并查集模板题
判断每两个字符串之间,如果相似或者相同,就并在一组
最后判断有多少组,即可
(最开始还以为并查集复杂度是 logn,一直以为 n * n * n * logn 超时了,想半天怎么快速比对两字符串,后面才发现,原来并查集复杂度是 O(α(n)),α(n) 不会超过 5,就近似于 O(1),所以不超时)
代码如下:
class Solution {
public:
int flag[305];
bool f[305];
int res;
bool test(string a, string b) {
int flag = 0;
for(int i = 0; i < a.size(); i++) {
if(a[i] != b[i]) flag++;
}
if(flag == 2 || flag == 0) return true;
else return false;
}
int find(int x) {
if(x == flag[x])
return x;
else{
return flag[x] = find(flag[x]);
}
}
void merge(int i, int j)
{
flag[find(i)] = find(j);
}
int numSimilarGroups(vector<string>& strs) {
for(int i = 0; i < strs.size(); i++) {
flag[i] = i;
}
for(int i = 0; i < strs.size(); i++) {
for(int j = i + 1; j < strs.size(); j++) {
if(test(strs[i], strs[j])) {
merge(i, j);
}
}
}
for(int i = 0; i < strs.size(); i++) {
int p = find(i);
if(f[p] == false) {
f[p] = true;
res++;
}
}
return res;
}
};