Two strings X
and Y
are similar if we can swap two letters (in different positions) of X
, so that it equals Y
. Also two strings X
and Y
are similar if they are equal.
For example, "tars"
and "rats"
are similar (swapping at positions 0
and 2
), and "rats"
and "arts"
are similar, but "star"
is not similar to "tars"
, "rats"
, or "arts"
.
Together, these form two connected groups by similarity: {"tars", "rats", "arts"}
and {"star"}
. Notice that "tars"
and "arts"
are in the same group even though they are not similar. Formally, each group is such that a word is in the group if and only if it is similar to at least one other word in the group.
We are given a list strs
of strings where every string in strs
is an anagram of every other string in strs
. How many groups are there?
Example 1:
Input: strs = ["tars","rats","arts","star"] Output: 2
Example 2:
Input: strs = ["omv","ovm"] Output: 1
思路:就是个union find,两个string similar就是diff <=2;
class Solution {
public class UnionFind {
public int[] father;
public int count;
public UnionFind(int n) {
this.count = n;
this.father = new int[n + 1];
for(int i = 0; i <= n; i++) {
father[i] = i;
}
}
public int find(int x) {
int j = x;
while(father[j] != j) {
j = father[j];
}
// path compression;
while(x != j) {
int fx = father[x];
father[x] = j;
x = fx;
}
return j;
}
public void union(int a, int b) {
int root_a = find(a);
int root_b = find(b);
if(root_a != root_b) {
father[root_a] = root_b;
count--;
}
}
}
public int numSimilarGroups(String[] strs) {
int n = strs.length;
UnionFind uf = new UnionFind(n);
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
if(isSimilar(strs[i], strs[j])) {
uf.union(i, j);
}
}
}
return uf.count;
}
private boolean isSimilar(String a, String b) {
int count = 0;
for(int i = 0; i < a.length(); i++) {
if(a.charAt(i) != b.charAt(i)) {
count++;
}
}
return count <= 2;
}
}