给定两个字符串 source
和 target
. 求 source
中最短的包含 target
中每一个字符的子串.
样例
样例 1:
输入: source = "abc", target = "ac"
输出: "abc"
样例 2:
输入: source = "adobecodebanc", target = "abc"
输出: "banc"
解释: "banc" 是 source 的包含 target 的每一个字符的最短的子串.
样例 3:
输入: source = "abc", target = "aa"
输出: ""
解释: 没有子串包含两个 'a'.
挑战
O(n) 时间复杂度
注意事项
- 如果没有答案, 返回
""
. - 保证答案是唯一的.
target
可能包含重复的字符, 而你的答案需要包含至少相同数量的该字符.
class Solution {
public:
/**
* @param source : A string
* @param target: A string
* @return: A string denote the minimum window, return "" if there is no such a string
*/
string minWindow(string &s , string &t) {
// write your code here
int start = 0; //记录返回的开始位置
int minlen = INT_MAX; //记录子串最短的长度,配合上面的start共同确定返回的子串
int left = 0; //滑动窗口的左边界
int right = 0; //滑动窗口的有边界
unordered_map<char, int> window;
unordered_map<char, int> needs;
for(char ch : t)
needs[ch]++; //做一个hash映射
int match = 0; //当前匹配到的长度
while(right < s.size())
{
char c1 = s[right];
if(needs.count(c1))
{
window[c1]++;
if(window[c1] == needs[c1])
match++; //说明匹配到了一个字符
}
right++;
while(match == needs.size())
{
if(right - left < minlen) //更新最小长度
{
minlen = right - left;
start = left; //更新开始位置
}
char c2 = s[left]; //开始缩进左边界
if(needs.count(c2))
{
window[c2]--;
if( window[c2] < needs[c2]) //如果当前窗口内的值不满足要求的话
match--;
}
left++;
}
}
return minlen == INT_MAX ? "" : s.substr(start, minlen);
}
};