给定一个字符串 s 和一些长度相同的单词 words。 找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置
注意子串要与 words 中的单词完全匹配,中间不能有其他字符,不需要考虑 words 中单词串联的顺序。
思路:
1. 用哈希表记录 words 中有哪些单词,以及出现的次数(检查每个s 子串时,哈希表都是新的)。
2. 遍历一个s的子串,将其截成一个个单词的长度,去哈希表中查询。
3. 如果出现在子串中的单词能在哈希表中找到,就将其数量 -1,对消掉一个。
4. 如果单词在哈希表中找不到,或者数量为0,说明不符合要求,可以停止程序了
5.若子串的单词都比较完毕,然后哈希表所有单词数量正常也都变成了0,就说明这个子串是我们要找的
var findSubstring = function(s, words) {
// 由于works里每一项字符串的长度固定,故取出第一项的长度即可
const wordSize = words[0].length
// works里每一项字符串加一起的总长度
const substringLen = wordSize * words.length
// hashMap 记录下 每一项出现的次数
// 最后wordsCount就像 --> { bar: 1, foo: 1}
const wordsCount = {}
words.forEach(w => (wordsCount[w] = (wordsCount[w] || 0) + 1))
// 最后的结果
const res = []
// 若传入字符串的总长度 < 数组字符串的总长度,肯定不符合 return []
// 总长度 - 数组字符串总长度,即为循环的次数
for (let i = 0; i <= s.length - substringLen; i++) {
// 每一次循环都需要复制hashMap
const tempCount = {...wordsCount}
// count 为数组有多少个字符串
let count = words.length
// 同时和数组字符串 截取再进行对比
for (let j = i; j < i + substringLen; j += wordSize) {
// 从0开始 截取字符串wordsize个字符串 判断是否在hashMap中
const word = s.slice(j, j + wordSize)
if (!(word in tempCount) || tempCount[word] <= 0) break
// 在hashMap中将count减1 并且将hashMap中的值减一
tempCount[word]--
count--
}
// 有且只有在count === 0时 才说明可以完全拼成,并将当前的i导入
if (count === 0) res.push(i)
}
return res
};