leetcode 30 串联所有单词的子串 - 实践
一、问题描述

二、解题思路
整体思路:
将words中的每个字符串看成一个整体,由于可以使用同向双指针来解决,且在解决的过程中可以实现指针不回退,所以可以使用滑动窗口+哈希表来解决这个问题。思路与leetcode483最小覆盖子串的思路一致。
具体思路:
(1)len表示words中单词的长度,哈希表need用于记录words中单词出现的频次,window用于记录窗口中单词出现的频次;
(2)由于起始位置可以是0,1,2,......len-1,所以需要在每一种起始情况下使用滑动窗口;
(3)滑动窗口要素:
<1>进窗口:进哈希表window
//进窗口
string in=s.substr(right,len);
window[in]++;
<2>出窗口:出哈希表window
//出窗口
while(right-left+1>words.size()*len){
string out=s.substr(left,len);
if(--window[out]==0) window.erase(out);
left+=len;
}
<3>更新:如果为串联子串,则将当前的left加入ret向量
//更新
if(window==need) ret.push_back(left);
注意:right和left以len的长度来后移
三、代码实现
方法一:
class Solution {
public:
vector findSubstring(string s, vector& words) {
map need,window;
vector ret;
int len=words[0].size();
//用word填充need
for(auto str:words) need[str]++;
for(int i=0;i!=len;i++){
window.clear();
for(int left=i,right=i;right+lenwords.size()*len){
string out=s.substr(left,len);
if(--window[out]==0) window.erase(out);
left+=len;
}
//更新
if(window==need) ret.push_back(left);
}
}
return ret;
}
};
方法二:
将map更换为unorderd_map,为了避免window==need的比较,定义变量count来简化比较 的复杂度,优化后代码如下:
class Solution {
public:
vector findSubstring(string s, vector& words) {
unordered_map need;//用于记录words中单词出现的频次
for(auto str:words) need[str]++;
unordered_map window;//用于记录窗口中中单词出现的频次
int len=words[0].size();
vector ret;
for(int i=0;i!=len;i++){
int count=0;
window.clear();
for(int right=i,left=i;right+lenwords.size()*len){
string out=s.substr(left,len);
if(window[out]--<=need[out]) count--;
left+=len;
}
//更新
if(count==words.size()) ret.push_back(left);
}
}
return ret;
}
};

浙公网安备 33010602011771号