1813.句子相似性 III

【LetMeFly】:“图解”1813.句子相似性 III

力扣题目链接:https://leetcode.cn/problems/sentence-similarity-iii/

一个句子是由一些单词与它们之间的单个空格组成,且句子的开头和结尾没有多余空格。比方说,"Hello World" ,"HELLO" ,"hello world hello world" 都是句子。每个单词都  包含大写和小写英文字母。

如果两个句子 sentence1 和 sentence2 ,可以通过往其中一个句子插入一个任意的句子(可以是空句子)而得到另一个句子,那么我们称这两个句子是 相似的 。比方说,sentence1 = "Hello my name is Jane" 且 sentence2 = "Hello Jane" ,我们可以往 sentence2 中 "Hello" 和 "Jane" 之间插入 "my name is" 得到 sentence1 。

给你两个句子 sentence1 和 sentence2 ,如果 sentence1 sentence2 是相似的,请你返回 true ,否则返回 false 。

 

示例 1:

输入:sentence1 = "My name is Haley", sentence2 = "My Haley"
输出:true
解释:可以往 sentence2 中 "My" 和 "Haley" 之间插入 "name is" ,得到 sentence1 。

示例 2:

输入:sentence1 = "of", sentence2 = "A lot of words"
输出:false
解释:没法往这两个句子中的一个句子只插入一个句子就得到另一个句子。

示例 3:

输入:sentence1 = "Eating right now", sentence2 = "Eating"
输出:true
解释:可以往 sentence2 的结尾插入 "right now" 得到 sentence1 。

示例 4:

输入:sentence1 = "Luky", sentence2 = "Lucccky"
输出:false

 

提示:

  • 1 <= sentence1.length, sentence2.length <= 100
  • sentence1 和 sentence2 都只包含大小写英文字母和空格。
  • sentence1 和 sentence2 中的单词都只由单个空格隔开。

方法一:双指针

为了方便处理,我们首先将句子拆分为单词。例如将Hello World拆分为[Hello, World]

接着对于单词列表1和单词列表2,分别使用首尾两个指针,指针指向两个单词列表中已经匹配上的部分。

为了方便理解,假设句子1为A E B C,句子2为A E C,那么:

1
2
3
4
5
6
单词1首指针                       单词1尾指针
↓ ↓
A E B C 👈单词1
A E C 👈单词2
↑ ↑
单词2首指针 单词2尾指针

接着在单词1和单词2的首指针的下一个单词匹配时,不断后移两个指针

1
2
3
4
5
6
    单词1首指针          单词1尾指针
↓ ↓
A E B C 👈单词1
A E C 👈单词2
↑ ↑
单词2首指针 单词2尾指针

不难发现两个单词列表的第一个单词A是匹配的,第二个单词B也是匹配的,但是第三个单词开始不匹配了。首指针的移动到此为止

接着开始移动尾指针

1
2
3
4
5
6
    单词1首指针      单词1尾指针
↓ ↓
A E B C 👈单词1
A E C 👈单词2
↑ ↑
单词2首指针 单词2尾指针

不难发现两个单词列表的最后一个单词C是匹配的,但是倒数第二个单词开始不匹配了。尾指针的移动到此为止

指针移动完毕,诶,单词列表2的首位指针相邻了!!!

这说明什么?这说明单词列表2的首指针所指过的单词,全都是单词列表1的“前缀”;而单词列表2的尾指针所指过的单词,全都是单词列表1的“后缀”

那不就说明单词列表1可以由单词列表2在中间添加数个连续的单词而得到么?

因此返回true即可

  • 时间复杂度$O(len(sentence1) + len(sentence2))$
  • 空间复杂度$O(len(sentence1) + len(sentence2))$

注意事项:

  1. 比较指针的下一个单词之前,记得检测指针的下一个单词是否在单词列表的合法范围内,以防止越界
  2. 在比较尾指针时,不但要保证指针的下一个所指下标大于等于0,还要保证下一个所指位置大于首指针(与首指针不重合,以防止某个单词匹配两次)

AC代码

C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
private:
vector<string> sentence2words(string& s) {
vector<string> ans;
int start = 0;
for (int i = 0; i <= s.size(); i++) {
if (i == s.size() || s[i] == ' ') {
ans.push_back(s.substr(start, i - start));
start = i + 1;
}
}
return ans;
}
public:
bool areSentencesSimilar(string& sentence1, string& sentence2) {
vector<string> words1 = sentence2words(sentence1), words2 = sentence2words(sentence2);
int front1 = -1, front2 = -1, back1 = words1.size(), back2 = words2.size();
while (front1 + 1 < words1.size() && front2 + 1 < words2.size() && words1[front1 + 1] == words2[front2 + 1]) {
front1++, front2++;
}
while (back1 - 1 > front1 && back2 - 1 > front2 && words1[back1 - 1] == words2[back2 - 1]) {
back1--, back2--;
}
return front1 + 1 == back1|| front2 + 1 == back2;
}
};

Python

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def areSentencesSimilar(self, sentence1: str, sentence2: str) -> bool:
words1 = sentence1.split()
words2 = sentence2.split()
front1, front2, back1, back2 = -1, -1, len(words1), len(words2)
while front1 + 1 < len(words1) and front2 + 1 < len(words2) and words1[front1 + 1] == words2[front2 + 1]:
front1 += 1
front2 += 1
while back1 - 1 > front1 and back2 - 1 > front2 and words1[back1 - 1] == words2[back2 - 1]:
back1 -= 1
back2 -= 1
return front1 + 1 == back1 or front2 + 1 == back2

同步发文于CSDN,原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/128710464


1813.句子相似性 III
https://blog.letmefly.xyz/2023/01/16/LeetCode 1813.句子相似性III/
作者
Tisfy
发布于
2023年1月16日
许可协议