题目描述:
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).
For example, S = "ADOBECODEBANC"
, T = "ABC"
, Minimum window is "BANC"
.
Note:
If there is no such window in S that covers all characters in T, return the empty string ""
.
If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.
分析:
题意:给定一个字符串S,一个匹配串T,在S中找到最小连续子串,使得它包含T中所有元素,如果找不到,则返回空串。假设S长度为n,时间复杂度要求为O(n)。
思路:这道题考察map应用和双指针法的组合。假设字符串S长度为n1,T长度为n2,初始化指针left = 0,right = 0,start = -1(标记答案起始位置),cnt = n2(保存还需查找的字符串T中的元素个数),用map统计字符串T中的字符。① 如果map包含s[right]且map[s[right]]减一之后大于0,说明元素s[right]已经匹配了一个,此时cnt减一。② 当cnt = 0时,说明已经找到一个符合要求的连续子串,如果它的长度比目前的答案小,那么更新答案的起始位置start和对应的长度ans = right - left + 1;如果map包含[s[left]]且map[s[left]]加一大于等于1,说明在下一组匹配中,需要多处理一个字符s[left],此时cnt加一、指针left加一。③ 在right小于n1的范围内遍历完一遍,返回答案。
时间复杂度为O(n1 + n2)。
代码:
#include <bits/stdc++.h>
using namespace std;
// slicing window
class Solution {
public:
string minWindow(string s, string t) {
int n1 = s.length(), n2 = t.length();
// Exceptional Case:
if(n1 == 0 || n2 == 0 || n1 < n2){
return "";
}
map<char, int> m;
// count t
for(int i = 0; i <= n2 - 1; i++){
m[t[i]]++;
}
// update the window: [left, right]
int left = 0, right = 0, ans = INT_MAX, start = -1, cnt = n2;
while(right <= n1 - 1){
if(m.count(s[right])){
if(--m[s[right]] >= 0){
cnt--;
}
while(cnt == 0){
if(right - left + 1 < ans){
ans = right - left + 1;
start = left;
}
if(m.count(s[left])){
if(++m[s[left]] >= 1){
cnt++;
}
}
left++;
}
}
right++;
}
if(start == -1){
return "";
}
return s.substr(start, ans);
}
};