思路
- 同向双指针实现滑动窗口
- 当窗口包含目标子串进行窗口左缩减
- 当窗口不包含目标子串进行窗口右扩展
- 如何检测窗口是否包含目标子串?——通过哈希计数,判断是否小于目标子串的计数
代码
步骤:
1. 目标子串计数
2. 初始化窗口右移
3. 判断是否满足条件——满足条件记录最小长度 并 进行左移
4. 记得<左移 右移>时需要对窗口计数进行更新
class Solution {
public:
unordered_map <char, int> ori, cnt;
bool check() {
for (const auto &p: ori)
if (cnt[p.first] < p.second)
return false;
return true;
}
string minWindow(string s, string t) {
for (const auto &c: t)
++ori[c];
int l = 0, r = -1;
int len = INT_MAX, ansL = -1;
while (r < int(s.size())) {
if (ori.find(s[++r]) != ori.end())
++cnt[s[r]];
while (check() && l <= r) {
if (r - l + 1 < len) {
len = r - l + 1;
ansL = l;
}
if (ori.find(s[l]) != ori.end())
--cnt[s[l]];
++l;
}
}
return ansL == -1 ? string() : s.substr(ansL, len);
}
};
优化思路
- 窗口左端可能包含许多与目标子串无关的字母
eg: XXXXABC ABC
- 当窗口右端还没碰到目标子串任意字符时,可以
左右指针同时移动
或 左指针等于右指针
- 如何判断窗口不包含任意子串字符?——与check类似,但判断的出现次数改为0
class Solution {
public:
unordered_map <char, int> ori, cnt;
bool check() {
for (const auto &p: ori)
if (cnt[p.first] < p.second)
return false;
return true;
}
bool check_is_null() {
for (const auto &p: ori)
if (cnt[p.first]!=0)
return false;
return true;
}
string minWindow(string s, string t) {
for (const auto &c: t)
++ori[c];
int l = 0, r = -1;
int len = INT_MAX, ansL = -1;
while (r < int(s.size())) {
if (ori.find(s[++r]) != ori.end())
++cnt[s[r]];
else if(check_is_null())
{ l=r;continue; }
while (check() && l <= r) {
if (r - l + 1 < len) {
len = r - l + 1;
ansL = l;
}
if (ori.find(s[l]) != ori.end())
--cnt[s[l]];
++l;
}
}
return ansL == -1 ? string() : s.substr(ansL, len);
}
};