本文是滑动窗口技巧
典型题目:
———–
这个是最基础,最典型的滑动窗口问题,记忆并理解其中的细节,类似的就可以套用处理了
条件是包含字串,所以算法思路是先找到符合条件的字符串,然后缩小到最小,更新最优解,再接着找下一解
class Solution {
public:
string minWindow(string s, string t) {
unordered_map<char, int> need,window;
//装载need
for (auto c : t) need[c]++;
int left = 0, right = 0, start = 0, len = INT_MAX, length = s.length(), valid = 0;
while (right < length) {
char c = s[right];
right++;
//更新window
if (need.find(c) != need.end()) {
window[c]++;
if (window[c] == need[c])
valid++;
}
//printf("window[%d, %d)\n", left, right); //出错,此处debug
//判断何时需要左移缩小窗口(关键,也是难点)
while (valid == need.size()) {
//更新最优解
if (right - left < len) {
start = left;
len = right - left;
}
char c = s[left];
left++;
if (need.find(c) != need.end()) {
if (window[c] == need[c])
valid--;
window[c] --;
}
}
}
return len == INT_MAX ? "" : s.substr(start, len);
}
};
条件实质是找子串的异位串,所以算法思路是先让窗口大小与字串大小一致,然后判断是否互相异位
class Solution {
public:
bool checkInclusion(string s1, string s2) {
unordered_map<char, int> need, window;
for (char c : s1) need[c]++;
int left = 0, right = 0, len1 = s1.length(), len2 = s2.length(), valid = 0;
while (right < len2) {
char c = s2[right];
right++;
//更新window
if (need.find(c) != need.end()) {
window[c]++;
if (need[c] == window[c]) valid++;
}
//判断什么时候需要缩小window
while (right - left >= len1) {
if (valid == need.size()) return true;
char c = s2[left];
left++;
if (need.find(c) != need.end()) {
if (need[c] == window[c]) valid--;
window[c]--;
}
}
}
return false;
}
};
这个跟上题一样,多了个记录索引输出
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
vector<int> ret;
unordered_map<char, int> need, window;
for (char c : p) need[c]++;
int left = 0, right = 0, len1 = s.length(), len2 = p.length(), valid = 0;
while (right < len1) {
char c = s[right];
right++;
if (need.find(c) != need.end()) {
window[c]++;
if (need[c] == window[c]) valid++;
}
while (right-left >= len2) {
if (valid == need.size()) ret.push_back(left);
char c = s[left];
left++;
if (need.find(c) != need.end()) {
if (need[c] == window[c]) valid--;
window[c]--;
}
}
}
return ret;
}
};
变形较大,无重复就行,所以没有具体的need窗口,条件是无重复,所以算法思路一直扩大窗口,直到碰到重复串再缩小窗口
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<char, int> window;
int left = 0, right = 0, len = 0, slen = s.length();
while (right < slen) {
char c = s[right];
right++;
window[c]++;
while (window[c] > 1) {
char d = s[left];
left++;
window[d]--;
}
len = max(len, right-left);
}
return len;
}
};