题目描述
给出两个字符串 S 和 T,要求在O(n)O(n)的时间复杂度内在 S 中找出最短的包含 T 中所有字符的子串。
例如:
S =“XDOYEZODEYXNZ”
T =“XYZ”
找出的最短子串为"YXNZ"
注意:
如果 S 中没有包含 T 中所有字符的子串,返回空字符串 “”;
满足条件的子串可能有很多,但是题目保证满足条件的最短的子串唯一。
示例1
输入 “XDOYEZODEYXNZ”,“XYZ”
返回值 “YXNZ”
题解:
----j--------i-------
当 i 向后移动时,j 只能向后移动,不能向前移动,原因:假设 区间[ j,i ] 已经包含所需要的字符,j 向前移动依旧包含,题目要求解的是最小的,因此 j 无法向前移动,可以使用滑动窗口,两个指针同步移j动。
- j 何时向后移动:当区间中的j 指向的字符已经包含且大于 T 中该字符的个数,此时需要向后移动。
- 如何知道 T 中特定字符个数且随时获取呢?选用hash 来存储 T 中的字符及其数量的对应关系。 区间中的字符的数量也需要使用hash来存储。
- 还需要一个变量来记录区间中有效的在T中的元素的个数。如果区间中cnt个数已经等于T中的元素总数,那么需要更新res,由于需要最小的覆盖子串,因此需要更新时需要判断此时区间覆盖长度是否小于原先的覆盖子串的长度。
class Solution {
public:
string minWindow(string S, string T) {
// write code heres
unordered_map<char,int> hs,ht;
for(auto x:T) ht[x]++;
string res;
int cnt=0;
for(int i=0,j=0;i<S.size();i++)
{
hs[S[i]]++;
if(hs[S[i]]<=ht[S[i]]) cnt++;
while( hs[S[j]] > ht[S[j]]) hs[S[j++]]--;
if(cnt==T.size())
{
if(res.empty()||i-j+1 < res.size())
res=S.substr(j,i-j+1);
}
}
return res;
}
};