📅  最后修改于: 2023-12-03 15:12:46.272000             🧑  作者: Mango
这是 门 | 门 IT 2005 往年的一道算法题,属于中等难度,需要对数据结构和算法有一定的掌握。
给定一个字符串 s 和一组长度相同的单词列表 words,在 s 中找出可以恰好由 words 中所有单词串联形成的子串的起始位置。 注意子串要恰好由 words 中所有单词串联,不多不少。
例如,给定: s="barfoothefoobarman" words=["foo", "bar"] 可以得到的结果: [0,9]
这道题目需要用到哈希表和双指针两个数据结构。
首先,将单词列表中的所有单词存储在一个哈希表中,每个单词的键值对是单词及其出现次数。然后,在字符串 s 中遍历所有的子串,并判断是否由单词列表中的单词串联形成。
我们可以选取一个窗口,窗口的长度正好为单词列表中所有单词的长度和。然后,我们可以将窗口移动,直到我们遍历完整个字符串。
在移动窗口时,我们可以使用两个指针,一个指向当前窗口的起始位置,另一个指向当前窗口的末尾位置。我们还需要一个哈希表,用于记录我们窗口中出现的单词及其出现的次数。
在每次移动窗口时,我们可以将当前窗口的末尾位置向右移动一个单词的长度,并判断当前窗口中的单词是否能够由单词列表中的单词串联形成。如果能够形成,我们就可以将当前窗口的起始位置向右移动一个单词的长度,继续判断是否存在符合条件的子串。如果窗口中存在没有在单词列表中出现的单词,或者某个单词在窗口中出现的次数大于其在单词列表中出现的次数,则说明这个子串不能由单词列表中的单词串联形成,我们就可以直接退出循环。
最后,我们可以将符合条件的子串的起始位置存储在一个列表中,并返回这个列表即可。
下面是这道题目的代码实现,使用 Python 语言编写。代码实现过程中,我们使用了哈希表和双指针两个数据结构:
def findSubstring(s: str, words: List[str]) -> List[int]:
# 特判
if not s or not words:
return []
# 存储单词及其出现的次数
word_map = {}
for word in words:
word_map[word] = word_map.get(word, 0) + 1
# 单词列表中所有单词的长度相同
word_len = len(words[0])
# 存储符合条件的子串的起始位置
res = []
# 遍历所有子串
for i in range(len(s) - len(words) * word_len + 1):
# 存储当前窗口中出现的单词及其出现的次数
cur_map = {}
j = 0
while j < len(words):
word = s[i + j * word_len: i + (j + 1) * word_len]
# 如果当前单词不在单词列表中,直接退出循环
if word not in word_map:
break
cur_map[word] = cur_map.get(word, 0) + 1
# 如果当前单词出现的次数大于其在单词列表中出现的次数,直接退出循环
if cur_map[word] > word_map[word]:
break
j += 1
# 如果窗口中出现的单词及其出现的次数与单词列表中相同,则说明该窗口符合条件
if j == len(words):
res.append(i)
return res
以上即为 门 | 门 IT 2005 中第 46 题的解析。这题考察了开发者对数据结构和算法的掌握程度,需要学好基础知识才能更好地解题。