1 题目描述
给出两个字符串 S 和 T,要求在O(n)的时间复杂度内在 S 中找出最短的包含 T 中所有字符的子串。
例如:
S=“XDOYEZODEYXNZ”
T=“XYZ”
找出的最短子串为"YXNZ".
注意:
如果 S 中没有包含 T 中所有字符的子串,返回空字符串 “”;
满足条件的子串可能有很多,但是题目保证满足条件的最短的子串唯一。
2 解题思路
这道题的思路是:
- begin开始指向0, end一直后移,直到begin - end区间包含T中所有字符。
记录窗口长度d - 然后begin开始后移移除元素,直到移除的字符是T中的字符则停止,此时T中有一个字符没被
包含在窗口, - 继续后移end,直到T中的所有字符被包含在窗口,重新记录最小的窗口d。
- 如此循环知道end到S中的最后一个字符。
时间复杂度为O(n)
3 代码实现
#include <string>
#include <unordered_map>
using namespace std;
class Solution {
public:
/**
*
* @param S string字符串
* @param T string字符串
* @return string字符串
*/
string minWindow(string S, string T) {
// write code here
unordered_map<char, int> window, target;
for (char c : T) ++target[c];
int left = 0, right = 0;
int start = 0, minLen=INT32_MAX;
int count = 0; // 记录窗口中字符是否满足目标
while (right < S.size()) {
char c = S[right];
++right;
if (target.count(c)) {
++window[c];
if (window[c] == target[c]) ++count;
}
while (count == target.size()) {
if (right-left < minLen) {
start = left;
minLen = right-left;
}
c = S[left];
++left;
if (target.count(c)) {
if (window[c] == target[c]) --count;
--window[c];
}
}
}
return minLen==INT32_MAX ? "" : S.substr(start, minLen);
}
};
4 运行结果
运行时间:2ms
占用内存:356k