[Leetcode 734] 句子相似性

我们可以将一个句子表示为一个单词数组,例如,句子 "I am happy with leetcode" 可以表示为 arr = ["I", "am", happy", "with", "leetcode"]
给定两个句子 sentence1 和 sentence2 分别表示为一个字符串数组,并给定一个字符串对 similarPairs ,其中 similarPairs[i] = [xi, yi] 表示两个单词 xi and yi 是相似的。
如果 sentence1 和 sentence2 相似则返回 true ,如果不相似则返回 false 。
两个句子是相似的,如果:
  • 它们具有 相同的长度 (即相同的字数)
  • 对于每个位置 isentence1[i] 和 sentence2[i] 要么完全相同,要么它们在 similarPairs 中被定义为相似。
请注意:
  • 一个词总是与它自己相似
  • 相似关系是不可传递的。 例如,如果单词 a 和 b 是相似的,单词 b 和 c 也是相似的,那么 a 和 c  不一定相似 。
示例 1:
示例 2:
示例 3:
说明:
  • 1 <= sentence1.length, sentence2.length <= 1000
  • 1 <= sentence1[i].length, sentence2[i].length <= 20
  • sentence1[i] 和 sentence2[i] 只包含大小写英文字母
  • 0 <= similarPairs.length <= 2000
  • similarPairs[i].length == 2
  • 1 <= xi.length, yi.length <= 20
  • 所有对 (xi, yi) 都是 不同 的
 

解法一:哈希集合存相似单词对 (推荐)

对比两个句子,需要对每个位置判断:如果两个词相等,直接通过;如果不相等,就检查它们是否是已知相似对。
最简单的做法是把所有相似单词对放进一个哈希集合。
由于单词对的相似关系是对称的,有两种写法:
  1. 只存原始 (x, y),查询时同时查 (x, y)(y, x)
  1. 预处理时把 (x, y)(y, x) 都存进去,查询时只查一次。
第一种写法更省一点空间, 哈希集合里的 key 是一个二元组(x, y),这样查相似关系就是平均 O(1)
复杂度分析
n 是句子中的单词数,ksimilarPairs 的数量,m 是单词平均长度。
  • 时间复杂度:O((n + k) * m)
    • 构建哈希集合需要处理 k 个相似对: O(k * m)
    • 逐词比较两个句子需要 n 次字符串比较和哈希查询,时间复杂度是 O(n * m)
  • 空间复杂度:O(k * m)
    • 用于存储所有相似单词对。

解法二:哈希表 + 哈希集合

另一种写法是建立一个映射:word_to_similar[word] = set(所有与 word 相似的词)
比如,similarPairs = [["great", "fine"], ["acting", "drama"]] 可以建成:
这样比较 sentence1[i]sentence2[i] 时,只需要判断 sentence2[i] in word_to_similar[sentence1[i]]
这个写法的好处是语义更明确:每个单词直接对应一组相似词。尤其当一个词有很多相似词时,哈希集合查询仍然是平均 O(1)
复杂度分析
设:n 是句子长度,k 是相似单词对数量,m 是单词平均长度。
  • 时间复杂度:O((n + k) * m)
  • 空间复杂度是:O(k * m)
    • 因为每个相似对会被双向存储。

总结

这题按位置比较两个句子。两个句子长度不同一定不相似;长度相同时,每个位置上的两个单词要么相等,要么必须是题目给出的相似单词对。因为相似关系是对称但不传递的,所以不需要并查集。
这两种写法本质完全一样,都是用哈希结构加速“两个词是否直接相似”的查询。
区别只是存储形式不同:
  • 哈希集合:存 pair,例如 ("great", "fine")
  • 哈希表 + 哈希集合: 存 adjacency list,例如 great -> {fine}
只需要判断直接相似关系,哈希集合已经足够。
Buy Me a Coffee
上一篇
[Leetcode 729] 日程安排 1
下一篇
[Leetcode 737] 句子相似性  II