Given two strings s
and t
of lengths m
and n
respectively, return the minimum window substring of s
such that every character in t
(including duplicates) is included in the window. If there is no such substring, return the empty string ""
.
The testcases will be generated such that the answer is unique.
A substring is a contiguous sequence of characters within the string.
Example 1:
Input: s = "ADOBECODEBANC", t = "ABC" Output: "BANC" Explanation: The minimum window substring "BANC" includes 'A', 'B', and 'C' from string t.
Example 2:
Input: s = "a", t = "a" Output: "a" Explanation: The entire string s is the minimum window.
Example 3:
Input: s = "a", t = "aa" Output: "" Explanation: Both 'a's from t must be included in the window. Since the largest window of s only has one 'a', return empty string.
Constraints:
m == s.length
n == t.length
1 <= m, n <= 105
s
andt
consist of uppercase and lowercase English letters.
Follow up: Could you find an algorithm that runs in O(m + n)
time?
题目要求在已知字符串s中找出能包含t中所有字符的最小子字符串。简单方法就是以s每个字符为起点,每次遍历字符t的长度。但这种时间复杂度为O(mn),题目要求时间复杂度为O(m+n). ‘
因此采用滑窗法,两根指针,一根代表子字符串开始,一根代表子字符串的结尾(结尾每次走一个字符,因此可以用循环来代替),用一个hashmap记录字符串t中每个字符出现的次数,遍历字符串t循环n次,此时遇到字符c后mp[c]++。遍历字符串s时,遇到t中存在的字符,将hashmap中的次数减少1。
class Solution {
public:
string minWindow(string s, string t) {
unordered_map<char, int> mp;
//遍历字符串t,记录字符出现次数
for(auto c : t) mp[c]++;
//start记录当前子字符串开始位置
//len记录当前最短符合要求的子字符串,初始值为最大值
//pos记录当前最短符合要求的子字符串开始位置,初始值为-1,即无符合要求子字符串
//count记录当前子字符串中包含t字符串所有字符的个数,每次mp[c]为0时更新一次
int start = 0, len = INT_MAX, pos = -1, count = 0;
for(int i=0; i<s.length(); i++){
if(!mp.count(s[i])) continue;
mp[s[i]]--;
if(mp[s[i]] == 0){
count++;
if(count < mp.size()) continue; //t中还有字符未全包含在当前子字符串中continue
//当前子字符串包含t中所有字符,收缩开始位置使得字符串最短
while(start <= i){
while(start<=i && !mp.count(s[start])) start++;
if(mp[s[start]] < 0){
mp[s[start]]++;
start++;
} else break;
}
//计算当前子字符串长度,更新结果
if(i-start+1 < len){
len = i-start+1;
pos = start;
}
//找下一个子字符串的开始位置
mp[s[start]]++;
start++;
count--;
while(start <= i){
while(start<=i && !mp.count(s[start])) start++;
if(mp[s[start]] < 0){
mp[s[start]]++;
start++;
} else break;
}
}
}
if(pos == -1) return "";
return s.substr(pos, len);
}
};