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
Note:
A.length <= 2000
A[i].length <= 1000
A.length * A[i].length <= 20000
All words in A consist of lowercase letters only.
All words in A have the same length and are anagrams of each other.
The judging time limit has been increased for this question.
inttraverseMethod(vector<string>& A){ unordered_set<string> unvisitedStrings(A.begin(), A.end()); queue<string> toVisit; int result = 0;
while (!unvisitedStrings.empty()) { // Push the first string into the queue // ++result; toVisit.push(*unvisitedStrings.begin()); unvisitedStrings.erase(unvisitedStrings.begin()); // Find the connected component // while (!toVisit.empty()) { // Get the front string // string toTest(toVisit.front()); toVisit.pop();
// Traverse all possible results from toVisit.front() // for (int i = 0; i < size; ++i) { for (int t = i + 1; t < size; ++t) { if (toTest[i] != toTest[t]) { swap(toTest[i], toTest[t]); if (unvisitedStrings.count(toTest)) { toVisit.push(toTest); unvisitedStrings.erase(toTest); if (unvisitedStrings.empty()) return result; } swap(toTest[i], toTest[t]); } } } } }
boolisSimilar(conststring& str1, conststring& str2){ int different = 0; for (int i = 0; i < size; ++i) { if (str1[i] != str2[i]) { if (different > 1) returnfalse; ++different; } }
returntrue; }
intunionFindingMethod(vector<string>& A){ int result = 0; length = A.size(); // int groupI, groupT; // Initially, each node belongs to its own group // for (int i = 0; i < length; ++i) group[i] = i;
for (int i = 0; i < length; ++i) { for (int t = i + 1; t < length; ++t) { // groupI = findGroup(i); // groupT = findGroup(t);
if (isSimilar(A[i], A[t])) { group[findGroup(i)] = findGroup(t); } } }
for (int i = 0; i < length; ++i) result += (group[i] == i); return result; }
boolisSimilar(conststring& str1, conststring& str2){ int different = 0; for (int i = 0; i < size; ++i) { if (str1[i] != str2[i]) { if (different > 1) returnfalse; ++different; } }
returntrue; }
intunionFindingMethod(vector<string>& A){ int result = 0; length = A.size(); // int groupI, groupT; // Initially, each node belongs to its own group // for (int i = 0; i < length; ++i) group[i] = i;
for (int i = 0; i < length; ++i) { for (int t = i + 1; t < length; ++t) { // groupI = findGroup(i); // groupT = findGroup(t);
if (isSimilar(A[i], A[t])) { group[findGroup(i)] = findGroup(t); } } }
for (int i = 0; i < length; ++i) result += (group[i] == i); return result; }
inttraverseMethod(vector<string>& A){ unordered_set<string> unvisitedStrings(A.begin(), A.end()); queue<string> toVisit; int result = 0;
while (!unvisitedStrings.empty()) { // Push the first string into the queue // ++result; toVisit.push(*unvisitedStrings.begin()); unvisitedStrings.erase(unvisitedStrings.begin()); // Find the connected component // while (!toVisit.empty()) { // Get the front string // string toTest(toVisit.front()); toVisit.pop();
// Traverse all possible results from toVisit.front() // for (int i = 0; i < size; ++i) { for (int t = i + 1; t < size; ++t) { if (toTest[i] != toTest[t]) { swap(toTest[i], toTest[t]); if (unvisitedStrings.count(toTest)) { toVisit.push(toTest); unvisitedStrings.erase(toTest); if (unvisitedStrings.empty()) return result; } swap(toTest[i], toTest[t]); } } } } }
boolisSimilar(conststring& str1, conststring& str2){ int different = 0; for (int i = 0; i < size; ++i) { if (str1[i] != str2[i]) { if (different > 1) returnfalse; ++different; } }
returntrue; }
intunionFindingMethod(vector<string>& A){ int result = 0; length = A.size(); // Initially, each node belongs to its own group // for (int i = 0; i < length; ++i) group[i] = i;
for (int i = 0; i < length; ++i) { for (int t = i + 1; t < length; ++t) { if (isSimilar(A[i], A[t])) { group[findGroup(t)] = findGroup(i); } } }
for (int i = 0; i < length; ++i) result += (group[i] == i); return result; }
inttraverseMethod(vector<string>& A){ // Time complexity: O(size * size * length * log(length)) unordered_set<string> unvisitedStrings(A.begin(), A.end()); queue<string> toVisit; int result = 0;
while (!unvisitedStrings.empty()) { // Push the first string into the queue // ++result; toVisit.push(*unvisitedStrings.begin()); unvisitedStrings.erase(unvisitedStrings.begin()); // Find the connected component // while (!toVisit.empty()) { // Get the front string // string toTest(toVisit.front()); toVisit.pop();
// Traverse all possible results from toVisit.front() // for (int i = 0; i < size; ++i) { for (int t = i + 1; t < size; ++t) { if (toTest[i] != toTest[t]) { swap(toTest[i], toTest[t]); if (unvisitedStrings.count(toTest)) { toVisit.push(toTest); unvisitedStrings.erase(toTest); if (unvisitedStrings.empty()) return result; } swap(toTest[i], toTest[t]); } } } } }