滑动窗口
维护一个窗口,不断滑动;
for(int l = 0, r = 0; r < s.size();)
{
//增大窗口
win.add(s[r]);
r++;
//窗口右移
while(满足某个条件)
{
win.remove(s[l]);
l++;
//更新某个值
}
}
模板
void slidingWin(string str, string t)
{
unordered_map<int, int> hashmap, win;
for(char c : t) hashmap[c]++;
int valid = 0;
for(int l = 0, r = 0; r < str.size();)
{
//扩大窗口
char ch = str[r];
//窗口右移
r++;
//进行窗口内数据的一系列更新
...
cout << l << " " << r << endl;
//移动窗口
while()
{
//d是即将要移动出窗口的字符
char d = str[l];
//左移窗口
l++;
//更新结果
...
}
}
}
无重复字符的最长子串
题目链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<char, int> hashmap;
int cnt = 0;
for(int i = 0, j = 0; j < s.size(); j++)
{
hashmap[s[j]]++;
while(hashmap[s[j]] > 1) hashmap[s[i++]]--;
cnt = max(cnt, j - i + 1);
}
return cnt;
}
};
最小覆盖子串
题目链接:https://leetcode-cn.com/problems/minimum-window-substring/
class Solution {
public:
string minWindow(string s, string t) {
unordered_map<char, int> need, win;
for(int i = 0; i < t.size(); i++) need[t[i]]++;
//l和r分别是在当前字符串上维护的窗口的左右两端
int l = 0, r = 0;
int valid = 0;
//记录最小子串的起始位置和长度
int start = 0, cnt = INT_MAX;
while(r < s.size())
{
//即将进入窗口的字符
char ch = s[r];
//右移窗口
r++;
//进行窗口内数据的一系列更新
if(need.count(ch))
{
win[ch]++;
if(win[ch] == need[ch]) valid++;
}
//判断左侧窗口是否要收缩
while(valid == need.size())
{
//更新最小覆盖子串
if(r - l < cnt)
{
start = l;
cnt = r - l;
}
//向右滑动
char d = s[l];
l++;
if(need.count(d))
{
if(win[d] == need[d])
valid--;
win[d]--;
}
}
}
return cnt == INT_MAX ? "" : s.substr(start, cnt);
}
};
字符串的排列
题目链接:https://leetcode-cn.com/problems/permutation-in-string/
class Solution {
public:
bool checkInclusion(string s1, string s2) {
//维护一个窗口为s1.size的窗口,判断s1中是否包含s1的所有
unordered_map<int, int> hashmap, win;
for(char c : s1) hashmap[c]++;
int valid = 0;
for(int l = 0, r = 0; r < s2.size();)
{
//扩大窗口
char ch = s2[r];
//窗口右移
r++;
//进行窗口内数据的一系列更新 更新判断条件valid
//...
if(hashmap.count(ch))
{
win[ch]++;
if(win[ch] == hashmap[ch]) valid++;
}
cout << l << " " << r << endl;
//移动窗口 满足条件了进行更新 包含那个字符
while(r - l >= s1.size())
{
if(valid == hashmap.size()) return true;
//d是即将要移动出窗口的字符
char d = s2[l];
//左移窗口
l++;
//更新结果
//...
if(hashmap.count(d))
{
if(win[d] == hashmap[d])
valid--;
win[d]--;
}
}
}
return false;
}
};
找到字符串中所有字母异位词
题目链接:https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
vector<int> res;
unordered_map<char, int> hashmap, win;
for(auto ch : p) hashmap[ch]++;
int valid = 0;
for(int l = 0, r = 0; r < s.size();)
{
char ch = s[r];
r++;
if(hashmap.count(ch))
{
win[ch]++;
if(win[ch] == hashmap[ch]) valid++;
}
cout << l <<" " << r << " " << valid << endl;
while(r - l >= p.size())
{
if(valid == hashmap.size()) res.push_back(l);
char d = s[l];
l++;
if(hashmap.count(d))
{
if(win[d] == hashmap[d]) valid--;
win[d]--;
}
}
}
return res;
}
};