1. Description
You are given a string s and an array of strings words of the same length. Return all starting indices of substring(s) in s that is a concatenation of each word in words exactly once, in any order, and without any intervening characters.
You can return the answer in any order.
Example 1:
Input: s = "barfoothefoobarman", words = ["foo","bar"]
Output: [0,9]
Explanation: Substrings starting at index 0 and 9 are "barfoo" and "foobar" respectively.
The output order does not matter, returning [9,0] is fine too.
Example 2:
Input: s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]
Output: []
Example 3:
Input: s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]
Output: [6,9,12]
Constraints:
- 1 <= s.length <= 104
- s consists of lower-case English letters.
- 1 <= words.length <= 5000
- 1 <= words[i].length <= 30
- words[i] consists of lower-case English letters.
2. My code
function findSubstring(s: string, words: string[]): number[] {
const ans:number[]=[];
const singleWordLen=words[0].length;
const totalWordLen=singleWordLen*words.length;
if(totalWordLen>s.length){
return ans;
}
const wordMap={};
for(let i of words){
if(wordMap[i]){
wordMap[i]++;
}else{
wordMap[i]=1;
}
}
for(let i=0,len=s.length - totalWordLen,wordsLen=words.length;i<=len;i++){
let j=wordsLen,left=i,wordMapCopy={...wordMap};
while(j--){
const word=s.substr(left,singleWordLen);
const val=wordMapCopy[word];
if(val){
if(val===1){
delete wordMapCopy[word];
}else{
wordMapCopy[word]--;
}
left+=singleWordLen;
}else{
break;
}
}
if(!Object.keys(wordMapCopy).length){
ans.push(i);
}
}
return ans;
};
3. Summary
其他算法题还好,字符类的总是让我头疼,还好今天不畏惧挑战,看了下 java 思路,一次通关。
思路:
统计 words 中每个 word 出现的次数,用 hash 保存起来,以出现的字符串次数为value,word 为 key。
依次遍历 s 的每个字符串,以当前被遍历到的字符串为起点,匹配 hash 中的数据,匹配到了,对应 word 次数减 1 ,当 word 次数为 0 时删除该 key。