因为字符串中只有大小写字母,故可以用长度为60的数组模拟哈希表。
- 把字符串
t
的每个字符存入哈希表,哈希表的键表示字母,值表示该字母在整个字符串中出现的次数;- 遍历字符串
s
,用滑动窗口的思想,保持窗口左侧不动,只将窗口右侧向右移动,移动窗口的同时在哈希表中减去窗口内出现相应字母的次数。如果遍历到某一窗口时,哈希表中的值全都小于等于0
,则表示窗口内已经包含了所有匹配的字符;- 这是开始将窗口左侧向右移动,同时更新子串的最短长度。
class Solution {
public:
string minWindow(string s, string t) {
if (s.length() < t.length()) return "";
string res = "";
int st = 0;
int minLength = s.length() + 1;
//因为在ASCII表中,从‘A’到‘z’只有57位,开一个60的数组够用了
vector<int> hash(60, 0);
for (int i = 0; i < t.length(); ++ i) //构建哈希表
{
hash[t[i] - 'A'] ++ ;
hash[s[i] - 'A'] -- ;
}
if (areAllZero(hash)) return s.substr(0, t.length());
for (int i = t.length(); i < s.length(); ++ i)
{
hash[s[i] - 'A'] -- ; //滑动窗口右侧向右移动
while (areAllZero(hash)) //直到窗口内包含所有匹配字符为止
{
if (i - st + 1 < minLength) //当前子串长度小于最小子串长度时,更新
{
minLength = i - st + 1;
res = s.substr(st, minLength);
}
hash[s[st ++ ] - 'A'] ++ ; //滑动窗口左侧向右移动
}
}
return res;
}
//判断数组中是否所有元素都小于等于0
bool areAllZero(vector<int>& hash)
{
for (int &x : hash)
if (x > 0) return false;
return true;
}
};