737. 句子相似性 II
我们可以将一个句子表示为一个单词数组,例如,句子 I am happy with leetcode"可以表示为 arr = ["I","am",happy","with","leetcode"]
给定两个句子 sentence1 和 sentence2 分别表示为一个字符串数组,并给定一个字符串对 similarPairs ,其中 similarPairs[i] = [xi, yi] 表示两个单词 xi 和 yi 是相似的。
如果 sentence1 和 sentence2 相似则返回 true ,如果不相似则返回 false 。
两个句子是相似的,如果:
- 它们具有 相同的长度 (即相同的字数)
sentence1[i]和sentence2[i]是相似的
请注意,一个词总是与它自己相似,也请注意,相似关系是可传递的。例如,如果单词 a 和 b 是相似的,单词 b 和 c 也是相似的,那么 a 和 c 也是 相似 的。
示例 1:
输入: sentence1 = ["great","acting","skills"], sentence2 = ["fine","drama","talent"], similarPairs = [["great","good"],["fine","good"],["drama","acting"],["skills","talent"]]
输出: true
解释: 这两个句子长度相同,每个单词都相似。
示例 2:
输入: sentence1 = ["I","love","leetcode"], sentence2 = ["I","love","onepiece"], similarPairs = [["manga","onepiece"],["platform","anime"],["leetcode","platform"],["anime","manga"]]
输出: true
解释: "leetcode" --> "platform" --> "anime" --> "manga" --> "onepiece".
因为“leetcode”和“onepiece”相似,而且前两个单词是相同的,所以这两句话是相似的。
示例 3:
输入: sentence1 = ["I","love","leetcode"], sentence2 = ["I","love","onepiece"], similarPairs = [["manga","hunterXhunter"],["platform","anime"],["leetcode","platform"],["anime","manga"]]
输出: false
解释: “leetcode”和“onepiece”不相似。
提示:
1 <= sentence1.length, sentence2.length <= 10001 <= sentence1[i].length, sentence2[i].length <= 20sentence1[i]和sentence2[i]只包含大小写英文字母0 <= similarPairs.length <= 2000similarPairs[i].length == 21 <= xi.length, yi.length <= 20xi和yi只含英文字母
/**
* @param {string[]} sentence1
* @param {string[]} sentence2
* @param {string[][]} similarPairs
* @return {boolean}
*/
var areSentencesSimilarTwo = function(sentence1, sentence2, similarPairs) {
const sentenceLen1 = sentence1.length;
const sentenceLen2 = sentence2.length;
if (sentenceLen1 !== sentenceLen2) {
return false;
}
const similarLength = similarPairs.length;
if (!similarLength) {
return false;
}
const map = new Map();
for (let i = 0; i < similarLength; i++) {
for (let j = 0; j < 2; j++) {
if (!map.has(similarPairs[i][j])) {
map.set(similarPairs[i][j], map.size);
}
}
}
const unionFind = new UnionFind(map.size);
for (let i = 0; i < similarLength; i++) {
unionFind.union(map.get(similarPairs[i][0]), map.get(similarPairs[i][1]));
}
for (let i = 0; i < sentenceLen1; i++) {
if (!unionFind.checkUnion(map.get(sentence1[i]), map.get(sentence2[i]))) {
return false;
}
}
return true;
};
class UnionFind {
constructor(count) {
this.count = count;
this.parents = [];
this.sizes = new Array(count).fill(1);
this.init();
}
init() {
for (let i = 0; i < this.count; i++) {
this.parents[i] = i;
}
}
find(node) {
let curNode = node;
while (this.parents[curNode] !== curNode) {
this.parents[curNode] = this.parents[this.parents[curNode]];
curNode = this.parents[curNode];
}
return curNode;
}
union(left, right) {
const leftRoot = this.find(left);
const rightRoot = this.find(right);
if (leftRoot !== rightRoot) {
if (this.sizes[leftRoot] < this.sizes[rightRoot]) {
this.parents[leftRoot] = rightRoot;
this.sizes[rightRoot] += this.sizes[leftRoot];
} else {
this.parents[rightRoot] = leftRoot;
this.sizes[leftRoot] += this.sizes[rightRoot];
}
this.count--;
return true;
}
return false;
}
checkUnion(left, right) {
return this.find(left) === this.find(right);
}
}