1,题目要求
Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).
Example:
Input: S = "ADOBECODEBANC", T = "ABC"
Output:"BANC"
Note:
- If there is no such window in S that covers all characters in T, return the empty string “”.
- If there is such window, you are guaranteed that there will always be only one unique minimum window in S.
给定一个字符串S和一个字符串T,找到S中的最小窗口,它将包含复杂度为O(n)的T中的所有字符。
2,题目思路
对于这道题,要求求出在字符串S中包含字符串T所有字符的子串最小长度。
因为题目要求需要在O(n)的时间范围内完成,因此,我们可以定义一个滑动窗口在S上移动,用这种策略来找最短的子串。
对于字符是否完全出现问题,一般我们都是使用的hash表来实现字母与出现次数的映射。直接以ASCII为下标是一种比较方便的技巧。
其次,在遍历的过程中,我们会统计从当前开始位置到遍历位置,s的子串中是否包含了t的所有字符。
如果包含了所有的字符,那么:
1,我们需要计算当前合法子串的长度是否更短,如果更短,就更新结果,并记录当前子串的开始位置。
2,将之前hash为了计算而进行减一操作的字符恢复原值,并更新下一轮遍历的开始位置。
附带LeetCode中的discussion:
Here is a 10-line template that can solve most ‘substring’ problems
3,代码实现
static const auto s = []() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
return nullptr;
}();
class Solution {
public:
string minWindow(string s, string t) {
vector<int> hashMap(128, 0);
for(auto &c : t)
hashMap[c]++;
int counter = t.size();
int begin = 0, end = 0;
int resLen = INT_MAX, resHead = 0;
while(end < s.size()){
//说明当前字符在t中
if(hashMap[s[end++]]-- > 0)
counter--;
//找到了一个结果
while(counter == 0){
if(end - begin < resLen){
resLen = end - begin;
resHead = begin;
}
//将hashMap恢复,并更新开始位置
if(hashMap[s[begin++]]++ == 0)
counter++;
}
}
return resLen == INT_MAX? "" : s.substr(resHead, resLen);
}
};