滑动窗口问题的通用解题思路:
https://labuladong.gitbook.io/algo/di-ling-zhang-bi-du-xi-lie/hua-dong-chuang-kou-ji-qiao-jin-jie
给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字符的最小子串。
示例:
输入: S = “ADOBECODEBANC”, T = “ABC”
输出: “BANC”
说明:
如果 S 中不存这样的子串,则返回空字符串 ""。
如果 S 中存在这样的子串,我们保证它是唯一的答案。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-window-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
注意事项:
- s可能会比t还要小。
- t中可能会有重复的数字
- 在比较是否符合条件时,需要判断的是cur中的字符数量小于目标的字符串,而不是不等于。
s = "aaaaaabbbccccdd"
t = "abcd"
这种条件就是需要包含多个b和c,如果按照!=
来判断是肯定不行的
效率托底,但总比暴力枚举要好一些
解题思路:
维护两个指针,两个指针构成了一个结果的窗口,从左向右滑动
滑动终止条件是右侧指针滑到最右侧时。
每次向右滑动一次,将当前right指针指向的字符添加到hash表中,计数。
同时左侧指针也要判断是否向右滑动,当左侧指针指向的字符不在目标字符串中,或者当前的窗口中的当前字符的数量大于目标字符串中当前字符的数量时,向右侧滑动
typedef unordered_map<char, int> umci;
// 滑动窗口问题
// https://leetcode-cn.com/problems/minimum-window-substring/
// 76. 最小覆盖子串
// 还要考虑s的长度比t还要小。
// t中有重复的字符改怎么处理
string minWindow(string s, string t) {
if (s.size() < t.size())
return "";
int l = 0, r = 0;
umci target;
umci cur;
vector<std::pair<int, int>> res; // 存放l r的结果
for (int i = 0; i < t.size(); i++)
{
if (target.find(t[i]) != target.cend())
{
target[t[i]] = target[t[i]] + 1;
}
else
{
target.insert(make_pair(t[i], 1));
}
}
while (r < s.size())
{
char c = s[r];
umci::const_iterator it = target.find(c);
if (it != target.cend())
{
cur[c] = cur[c] + 1;
}
r++;
while (l < r)
{
// 2种情况,l会向右移动,1:当前字符不是t中的,2:当前字符是t中的,但是已经重复了
char cl = s[l];
if (target.find(cl) != target.cend())
{
int count = cur[cl];
if (count > target[cl])
{
l++;
cur[cl] = count - 1;
}
else
{
break; // 防止死循环
}
}
else
{
l++;
}
}
if (cur.size() == target.size())
{
// 还需要判断重复的字符
bool ok = true;
for (auto it = target.cbegin(); it != target.cend(); it++)
{
if (cur[it->first] < it->second) // 注意这里是小于
{
ok = false;
break;
}
}
if (ok)
res.push_back(make_pair(l, r));
}
}
if (res.size() > 0)
{
int minIndex = 0;
int curLen = s.size() + 1;
for (int i = 0; i < res.size(); i++)
{
int lp = res[i].first;
int rp = res[i].second;
if (rp - lp < curLen)
{
curLen = rp - lp;
minIndex = i;
}
}
return s.assign(s, res[minIndex].first, res[minIndex].second - res[minIndex].first);
}
return "";
}