题目
Given two sentences words1, words2 (each represented as an array of strings), and a list of similar word pairs pairs, determine if two sentences are similar.
For example, words1 = ["great", "acting", "skills"] and words2 = ["fine", "drama", "talent"] are similar, if the similar word pairs are pairs = [["great", "good"], ["fine", "good"], ["acting","drama"], ["skills","talent"]].
Note that the similarity relation is transitive. For example, if "great" and "good" are similar, and "fine" and "good" are similar, then "great" and "fine" are similar.
Similarity is also symmetric. For example, "great" and "fine" being similar is the same as "fine" and "great" being similar.
Also, a word is always similar with itself. For example, the sentences words1 = ["great"], words2 = ["great"], pairs = [] are similar, even though there are no specified similar word pairs.
Finally, sentences can only be similar if they have the same number of words. So a sentence like words1 = ["great"] can never be similar to words2 = ["doubleplus","good"].
Note:
- The length of
words1andwords2will not exceed1000. - The length of pairs will not exceed
2000. - The length of each
pairs[i]will be2. - The length of each
words[i]andpairs[i][j]will be in the range[1, 20].
解题思路
DFS
本题可以采用 DFS 的方法,把 pairs 数组中的每一对相似的字符串视为无向图上的两个端点,分别建立 pairs[i].first --> pairs[i].second 和 pairs[i].second --> pairs[i].first 的双向边,然后遍历 words1 和 words2[] 的每个字符串,查看是否存在一条 words[i] --> words2[i] 的路径。需要注意的是 visited 数组的设计,每次用 DFS 搜索 words1[i] 之前,要将该字符串设置为已访问,但在每次 DFS 结束后,还要将该字符串重置为未访问,这样再对下一个字符串 words1[i + 1] 进行 DFS 遍历,否则,在遍历 words1[i] 的过程中访问过的字符串在对 words1[i + 1] 进行访问时将无法访问到!
假设 E 为 pairs 数组的长度,words1 或 words2 的长度,则 DFS 的时间复杂度是 O(V+2E) ,相当可怕的复杂度。
并查集
可以用另一种观点来看待单词的相似:如果两个单词相似,则这两个单词属于同一类,因此在遍历 words1 和 words2 的每个单词的时候,只要判断两个单词是否属于同一类就能判断其是否相似。这样,问题就非常适合使用并查集来解决了。假设同一类的单词构成同一棵树,具体的步骤如下:
- 同时遍历
words1和word2中的每个单词,把每个单词的父结点设置为自己。 - 遍历
pairs数组中的每一对相似单词,把第二个单词的所在树的根结点的父节点设置为第一个单词所在的树的根结点,即把两棵同类的树进行合并。 - 遍历
words1和words2的每个单词,分别判断对应的两个单词所在树的根结点是否相同,若遇到根结点不相同的单词,则说明两个句子不相似。
C++代码实现
DFS
class Solution {
public:
bool areSentencesSimilarTwo(vector<string>& words1, vector<string>& words2, vector<pair<string, string>> pairs) {
if (words1.size() != words2.size()) { return false; }
unordered_map<string, vector<string> > dict;
unordered_map<string, bool> visited;
for (int i = 0; i < pairs.size(); ++i) {
dict[pairs[i].first].push_back(pairs[i].second);
dict[pairs[i].second].push_back(pairs[i].first);
visited[pairs[i].first] = visited[pairs[i].second] = false;
}
for (int i = 0; i < words1.size(); ++i) {
visited[words1[i]] = true;
if (!DFS(dict, words1[i], words2[i], visited)) { return false; }
visited[words1[i]] = false;
}
return true;
}
bool DFS(unordered_map<string, vector<string> >& dict, string src, string goal, unordered_map<string, bool>& visited) {
if (src == goal) { return true; }
bool flag = false;
for (int i = 0; i < dict[src].size(); ++i) {
if (visited[dict[src][i]]) { continue; }
visited[dict[src][i]] = true;
if (DFS(dict, dict[src][i], goal, visited)) { flag = true; }
visited[dict[src][i]] = false;
if (flag) { break; }
}
return flag;
}
};
并查集
class Solution {
public:
bool areSentencesSimilarTwo(vector<string>& words1, vector<string>& words2, vector<pair<string, string>> pairs) {
if (words1.size() != words2.size()) { return false; }
unordered_map<string, string> parents;
for (int i = 0; i < words1.size(); ++i) { parents[words1[i]] = words1[i]; }
for (int i = 0; i < words2.size(); ++i) { parents[words2[i]] = words2[i]; }
for (int i = 0; i < pairs.size(); ++i) {
string firstP = findParent(pairs[i].first, parents);
string secondP = findParent(pairs[i].second, parents);
parents[secondP] = firstP;
}
for (int i = 0; i < words1.size(); ++i) {
if (findParent(words1[i], parents) != findParent(words2[i], parents)) {
return false;
}
}
return true;
}
string findParent(string son, unordered_map<string, string>& parents) {
if (son == parents[son]) { return son; }
parents[son] = findParent(parents[son], parents);
return parents[son];
}
};
本文介绍了一种通过构建无向图和使用并查集算法来判断两个句子是否相似的方法。利用DFS遍历图寻找路径,或通过并查集判断单词是否属于同一类,以此来确定句子的相似性。
1064

被折叠的 条评论
为什么被折叠?



