Hard!
题目描述:
给定一个字符串 S 和一个字符串 T,请在 S 中找出包含 T 所有字母的最小子串。
示例:
输入: S = "ADOBECODEBANC", T = "ABC" 输出: "BANC"
说明:
- 如果 S 中不存这样的子串,则返回空字符串
""。 - 如果 S 中存在这样的子串,我们保证它是唯一的答案。
解题思路:
这道题的要求是要在O(n)的时间度里实现找到这个最小窗口字串,那么暴力搜索Brute Force肯定是不能用的,我们可以考虑哈希表,其中key是T中的字符,value是该字符出现的次数。
- 我们最开始先扫描一遍T,把对应的字符及其出现的次数存到哈希表中。
- 然后开始遍历S,遇到T中的字符,就把对应的哈希表中的value减一,直到包含了T中的所有的字符,纪录一个字串并更新最小字串值。
- 将子窗口的左边界向右移,略掉不在T中的字符,如果某个在T中的字符出现的次数大于哈希表中的value,则也可以跳过该字符。
C++解法一:
1 class Solution {
2 public:
3 string minWindow(string S, string T) {
4 if (T.size() > S.size()) return "";
5 string res = "";
6 int left = 0, count = 0, minLen = S.size() + 1;
7 unordered_map<char, int> m;
8 for (int i = 0; i < T.size(); ++i) {
9 if (m.find(T[i]) != m.end()) ++m[T[i]];
10 else m[T[i]] = 1;
11 }
12 for (int right = 0; right < S.size(); ++right) {
13 if (m.find(S[right]) != m.end()) {
14 --m[S[right]];
15 if (m[S[right]] >= 0) ++count;
16 while (count == T.size()) {
17 if (right - left + 1 < minLen) {
18 minLen = right - left + 1;
19 res = S.substr(left, minLen);
20 }
21 if (m.find(S[left]) != m.end()) {
22 ++m[S[left]];
23 if (m[S[left]] > 0) --count;
24 }
25 ++left;
26 }
27 }
28 }
29 return res;
30 }
31 };
这道题也可以不用哈希表,直接用个int的数组来代替,因为ASCII只有256个字符,所以用两个大小为256的int数组即可代替哈希表,其余部分的思路完全相同。
C++解法二:
1 class Solution {
2 public:
3 string minWindow(string S, string T) {
4 if (T.size() > S.size()) return "";
5 string res = "";
6 int left = 0, count = 0, minLen = S.size() + 1;
7 int tm[256] = {0}, sm[256] = {0};
8 for (int i = 0; i < T.size(); ++i) ++tm[T[i]];
9 for (int right = 0; right < S.size(); ++right) {
10 if (tm[S[right]] != 0) {
11 ++sm[S[right]];
12 if (sm[S[right]] <= tm[S[right]]) ++count;
13 while (count == T.size()) {
14 if (right - left + 1 < minLen) {
15 minLen = right - left + 1;
16 res = S.substr(left, minLen);
17 }
18 if (tm[S[left]] != 0) {
19 --sm[S[left]];
20 if (sm[S[left]] < tm[S[left]]) --count;
21 }
22 ++left;
23 }
24 }
25 }
26 return res;
27 }
28 };
来源:https://www.cnblogs.com/ariel-dreamland/p/9154343.html