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
Example 1:
Input: ["tars","rats","arts","star"]
Output: 2
Example 2:
Input: ["omv","ovm"]
Output: 1
Clarification
Anagram: a new word formed by changing the position (order) of the letters in a string.
Notice
1.A.length <= 2000
2.A[i].length <= 1000
3.A.length * A[i].length <= 20000
4.All words in A consist of lowercase letters only.
5.All words in A have the same length and are anagrams of each other.
public class Solution {
/**
* @param A: a string array
* @return: the number of groups
*/
public int numSimilarGroups(String[] A) {
// Write your code here
if (A == null || A.length == 0) {
return 0;
}
UF uf = new UF(A);
for (int i = 0; i < A.length; i++) {
for (int j = i + 1; j < A.length; j++) {
if (isSimilar(A[i], A[j])) {
uf.connect(A[i], A[j]);
}
}
}
return uf.getNumCC();
}
private boolean isSimilar(String s1, String s2) {
int first = -1;
int second = -1;
for (int i = 0; i < s1.length(); i++) {
char c1 = s1.charAt(i);
char c2 = s2.charAt(i);
if (c1 == c2) {
continue;
}
if (first == -1) {
first = i;
} else if (second == -1) {
second = i;
} else {
return false;
}
}
if (first == -1 && second == -1) {
return true;
}
if (s1.charAt(first) == s2.charAt(second) && s1.charAt(second) == s2.charAt(first)) {
return true;
}
return false;
}
}
class UF {
private Map<String, String> parents;
private int numCC;
public UF (String[] A) {
parents = new HashMap<>();
for (String a : A) {
parents.put(a, a);
}
numCC = parents.size();
}
public String find(String a) {
String root = a;
while (!root.equals(parents.get(root))) {
root = parents.get(root);
}
// path compression
while (!root.equals(a)) {
String parent = parents.get(a);
parents.put(a, root);
a = parent;
}
return root;
}
public void connect(String a, String b) {
String pa = find(a);
String pb = find(b);
if (!pa.equals(pb)) {
parents.put(pa, pb);
numCC--;
}
}
public int getNumCC() {
return numCC;
}
}
No comments:
Post a Comment