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;
}
};

posted @ 2025-08-24 21:19  wzzkaifa  阅读(7)  评论(0)    收藏  举报