839. Similar String Groups
Description
Two strings, X
and Y
, are considered similar if either they are identical or we can make them equivalent by swapping at most two letters (in distinct positions) within the string X
.
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
Constraints:
1 <= strs.length <= 300
1 <= strs[i].length <= 300
strs[i]
consists of lowercase letters only.- All words in
strs
have the same length and are anagrams of each other.
Solutions
Solution: Union Find
- Time complexity: O(n2*strs[i].length)
- Space complexity: O(n)
JavaScript
/**
* @param {string[]} strs
* @return {number}
*/
const numSimilarGroups = function (strs) {
const n = strs.length;
const groups = new Array(n)
.fill('')
.map((_, index) => index);
const isSimilar = (a, b) => {
let diff = 0;
for (const [index, element] of a.entries()) {
if (element === b[index]) continue;
diff += 1;
if (diff > 2) return false;
}
return true;
};
const unionFind = x => {
return groups[x] === x ? x : unionFind(groups[x]);
};
for (let a = 0; a < n - 1; a++) {
for (let b = a + 1; b < n; b++) {
if (!isSimilar(strs[a], strs[b])) continue;
const groupA = unionFind(a);
const groupB = unionFind(b);
groups[groupB] = groupA;
}
}
let result = 0;
for (let index = 0; index < n; index++) {
if (groups[index] === index) result += 1;
}
return result;
};