原题:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
有关双指针的思路可以参考:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
基本思路:滑动窗口(其实也是双指针的一种)
需要的变量:
两个指针:left、right
两个哈希map(姑且这么叫吧):win存储窗口中已存在的,need存储窗口中必须包含的
一个整型:done,记录win中已有多少字符的数量符合need的要求
基本步骤:
1. 右指针右移,扩大窗口,直到窗口符合need要求
2. 左指针右移,缩小窗口,直到窗口不符合要求
此时,left、right所包含的即为符合要求的子串
(可能有一些+1 -1之类的边界问题,需要具体分析)
3. 重复上述步骤,直到right越界
注意:扩大窗口与缩小窗口的代码很大程度上是对称的
class Solution {
public:
vector<int> findAnagrams(string src, string pat) {
unordered_map<char, int> win, need;
vector<int> ans;
int left = 0, right = 0;
int done = 0;
for (const char& i : pat) //初始化win与need
{
win[i] = 0;
need[i]++;
}
int size = need.size(); //size即为done需要达到的指标
while (right < src.size())
{
char in = src[right]; //待扩充的字符
right++; //总之先++再说,之后再考虑窗口是否符合条件
if (need.count(in)) //该字符在指标要求内时
{
win[in]++; //该字符进度增加
if (win[in] == need[in])
{
done++; //该字符已达成指标,done加1
}
}
//printf("A %d %d %d\n", left, right, done); //用于调试
while (done == size) //所有字符均达成指标,开始缩小窗口
{
char out = src[left]; //待删除字符
left++; //和right一样,总之先++
if (need.count(out)) //该字符在指标要求内时
{
win[out]--; //该字符进度减少
if (win[out] < need[out])
{
done--; //win中该字符数量已不足以达成指标,done减1
}
}
//printf("B %d %d %d\n", left, right, done);
if (right - left + 1 == pat.size() && done + 1 == size)
{
//进入该if语句时,说明上一次缩窗正好导致win无法完成指标
ans.push_back(left - 1); //上次缩窗前的left即为所求
}
}
}
return ans;
}
};