力扣题目:最小覆盖子串
- 最小覆盖子串
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
注意:
对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。
AC代码
class Solution {
public:
string minWindow(string s, string t)
{
unordered_map<char, int> hash; // 键值对 键是字符 值是该字符出现次数
for (int i = 0; i < t.size(); i ++ )
{
hash[t[i]] ++ ;
}
int left = 0, right = 0, n = s.size(), count = t.size();
int min_length = 1e6, min_left = 1e6, min_right = 1e6;
while (right < n)
{
// cout << "左边界,右边界为——" << left << "," << right << endl;
// cout << "count为——" << count << endl;
// 遍历到s[right]这个字符,判断t中是否需要有他
if (hash.find(s[right]) != hash.end()) // 等于end的时候,表示未找到
{
if (hash[s[right]] >= 1) // 如果这个字符还需要出现的次数>=1
{
count -- ; // 当count为0,则表示全找到了
} // 注意,可能等0 -1 -2,表示这个字符出现次数多了很多
hash[s[right]] -- ;
// cout << "s[right] = " << s[right] << endl;
// cout << hash[s[right]] << endl;
}
while (count == 0)
{
// cout << "找到一个答案\n";
// 每出现一次计数器为0,则表示当前长度内,是符合要求的,但可能不是最优
if (right - left + 1 < min_length)
{
// 更短,则更新答案
min_length = right - left + 1;
min_left = left;
min_right = right;
}
// 尝试左移left,看看能否符合条件并且缩小区间
if (hash.find(s[left]) != hash.end())
{
hash[s[left]] ++ ;
if (hash[s[left]] >= 1)
{
count ++ ; // hash[字符]表示字符还需要出现的次数,0表示刚好,1表示还要1个,-1表示多了1个
}
}
left ++ ;
}
right ++ ; // 窗口右边界后移
}
// cout << "min_length min_left min_right " << min_length << min_left << " " << min_right << endl;
string ret = "";
if (min_length != 1e6) ret = s.substr(min_left, min_length);
return ret;
}
};