Two strings X
and Y
are similar if we can swap two letters (in different positions) of X
, so that it equals Y
.
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 A
of strings. Every string in A
is an anagram of every other string in A
. How many groups are there?
Example 1:
Input: ["tars","rats","arts","star"] Output: 2
分析:
因为这个是找group,所以容易联想到用union-find.这里我们在确定谁是root的时候,总是挑index大的,这样才能把不同的groups合并成一个group.
1 public class Solution { 2 public int numSimilarGroups(String[] A) { 3 int[] roots = new int[A.length]; 4 for (int i = 0; i < A.length; i++) { 5 roots[i] = i; 6 } 7 for (int i = 1; i < A.length; i++) { 8 for (int j = 0; j < i; j++) { 9 if (similar(A[i], A[j])) { 10 roots[find(roots, j)] = i; 11 } 12 } 13 } 14 int result = 0; 15 for (int i = 0; i < roots.length; i++) { 16 if (roots[i] == i) { 17 result++; 18 } 19 } 20 return result; 21 } 22 private int find(int[] roots, int id) { 23 while (roots[id] != id) { 24 roots[id] = roots[roots[id]]; // path compression 25 id = roots[id]; 26 } 27 return id; 28 } 29 private boolean similar(String a, String b) { 30 int res = 0, i = 0; 31 boolean consecutive = false; 32 while (res <= 2 && i < a.length()){ 33 if (a.charAt(i) != b.charAt(i)) { 34 res++; 35 } 36 if (i > 1 && a.charAt(i) == a.charAt(i - 1)) { 37 consecutive = true; 38 } 39 i++; 40 } 41 return res == 2 || res == 0 && consecutive; 42 } 43 }