基本操作:
int left = 0, right = 0;
while (right < s.size()) {
// 增大窗口
window.add(s[right]);
right++;
while (window needs shrink) {
// 缩小窗口
window.remove(s[left]);
left++;
}
}
稳定模板:
/* 滑动窗口算法框架 */
void slidingWindow(string s, string t) {
unordered_map<char, int> need, window;
for (char c : t) need[c]++;
int left = 0, right = 0;
int valid = 0;
while (right < s.size()) {
// c 是将移入窗口的字符
char c = s[right];
// 右移窗口
right++;
// 进行窗口内数据的一系列更新
...
/*** debug 输出的位置 ***/
printf("window: [%d, %d)\n", left, right);
/********************/
// 判断左侧窗口是否要收缩
while (window needs shrink) {
// d 是将移出窗口的字符
char d = s[left];
// 左移窗口
left++;
// 进行窗口内数据的一系列更新
...
}
}
}
其中两处 ...
表示的更新窗口数据的地方,到时候你直接往里面填就行了。
#include <iostream>
#include <string>
#include <unordered_map>
#include <limits.h>
class Solution {
public:
std::string minWindow(std::string s, std::string t) {
std::unordered_map<char, int> need;
std::unordered_map<char, int> window;
int valid = 0;
int left = 0;
int right = 0;
int min_left = 0;
int min_len = INT_MAX;
// 初始化需求窗口
for (char c : t) {
need[c]++;
}
while (right < s.length()) {
char r_c = s[right];
right++;
if (need.count(r_c) != 0) {
window[r_c]++;
if (need[r_c] == window[r_c]) {
valid++;
}
}
while (valid == need.size()) {
if (right - left < min_len) {
min_left = left;
min_len = right - left;
}
char l_c = s[left];
left++;
if (window.count(l_c) != 0) {
if (need[l_c] == window[l_c]) {
valid--;
}
window[l_c]--;
}
}
}
return min_len == INT_MAX ? "" : s.substr(min_left, min_len);
}
};
#include <iostream>
#include <string>
#include <unordered_map>
#include <limits.h>
class Solution {
public:
bool checkInclusion(std::string s1, std::string s2) {
std::unordered_map<char, int> need;
std::unordered_map<char, int> window;
int valid = 0;
for (char c : s1) {
need[c]++;
}
int left = 0;
int right = 0;
while (right < s2.length()) {
char r_c = s2[right];
right++;
if (need.count(r_c)) {
window[r_c]++;
if (window[r_c] == need[r_c]) {
valid++;
}
}
while (valid == need.size()) {
if (right - left == s1.length()) {
return true;
}
char l_c = s2[left];
left++;
if (need.count(l_c)) {
if (need[l_c] == window[l_c]) {
valid--;
}
window[l_c]--;
}
}
}
return false;
}
};
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
class Solution {
public:
std::vector<int> findAnagrams(std::string s, std::string p) {
std::vector<int> res;
std::unordered_map<char, int> need;
std::unordered_map<char, int> window;
int left = 0;
int right = 0;
int valid = 0;
for (char c : p) {
need[c]++;
}
while (right < s.length()) {
char r_c = s[right];
right++;
if (need.count(r_c)) {
window[r_c]++;
if (need[r_c] == window[r_c]) {
valid++;
}
}
while (valid == need.size()) {
if (right - left == p.length()) {
res.push_back(left);
}
char l_c = s[left];
left++;
if (need.count(l_c)) {
if (need[l_c] == window[l_c]) {
valid--;
}
window[l_c]--;
}
}
}
return res;
}
};
class Solution {
public:
int lengthOfLongestSubstring(std::string s) {
std::unordered_map<char, int> windows;
int left = 0;
int right = 0;
int max_len = 0;
while (right < s.length()) {
char r_c = s[right];
right++;
windows[r_c]++;
while (windows[r_c] > 1) {
char l_c = s[left];
left++;
windows[l_c]--;
}
max_len = std::max(max_len, right - left);
}
return max_len;
}
};
使用回溯方法会超时
#include <set>
#include <vector>
#include <string>
#include <iostream>
#include <map>
#include <unordered_map>
class Solution {
public:
std::vector<int> findSubstring(std::string s, std::vector<std::string>& words) {
std::vector<int> res;
std::unordered_map<std::string, int> need;
std::unordered_map<std::string, int> window;
int left = 0;
int right = 0;
int valid = 0;
int start_pos = 0;
int word_len = words[0].length();
int words_len = words.size() * word_len;
std::set<int> visited;
for (auto& word : words) {
need[word]++;
}
// 多一层遍历,但是最多遍历到word_len,word_len之后的位置left都遍历过了
while (start_pos < word_len) {
left = start_pos;
right = start_pos;
valid = 0;
window.clear();
while (right + word_len <= s.length() && left + words_len <= s.length()) {
std::string str_r = s.substr(right, word_len);
right += word_len;
if (need.count(str_r)) {
window[str_r]++;
if (need[str_r] == window[str_r]) {
valid++;
// std::cout << " add startpos[" << start_pos << "] left:" << left << " right:" << right << " " << str_r << std::endl;
}
}
while (valid == need.size()) {
if (right - left == words_len) {
res.push_back(left);
// std::cout << "res startpos[" << start_pos << "] left:" << left << " right:" << right << std::endl;
}
std::string str_l = s.substr(left, word_len);
left += word_len;
if (need.count(str_l)) {
if (need[str_l] == window[str_l]) {
// std::cout << " del startpos[" << start_pos << "] left:" << left << " right:" << right << " " << str_l << std::endl;
valid--;
}
window[str_l]--;
}
}
}
start_pos++;
}
return res;
}
};