给你一个字符串 s
、一个字符串 t
。返回 s
中涵盖 t
所有字符的最小子串。如果 s
中不存在涵盖 t
所有字符的子串,则返回空字符串 ""
。
注意:
- 对于
t
中重复字符,我们寻找的子字符串中该字符数量必须不少于t
中该字符数量。 - 如果
s
中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC" 输出:"BANC"
示例 2:
输入:s = "a", t = "a" 输出:"a"
示例 3:
输入: s = "a", t = "aa" 输出: "" 解释: t 中两个字符 'a' 均应包含在 s 的子串中, 因此没有符合条件的子字符串,返回空字符串。
提示:
1 <= s.length, t.length <= 105
s
和t
由英文字母组成
进阶:你能设计一个在
o(n)
时间内解决此问题的算法吗?
滑动窗口
class Solution:
def minWindow(self, s: str, t: str) -> str:
ans = ''
m, n = len(s), len(t)
if m < n:
return ans
need = Counter(t)
window = Counter()
i, cnt, mi = 0, 0, float('inf')
for j, c in enumerate(s):
window[c] += 1
if need[c] >= window[c]:
cnt += 1
while cnt == n:
if j - i + 1 < mi:
mi = j - i + 1
ans = s[i: j + 1]
c = s[i]
if need[c] >= window[c]:
cnt -= 1
window[c] -= 1
i += 1
return ans
class Solution {
public String minWindow(String s, String t) {
Map<Character, Integer> mp = new HashMap<>();
int begin = 0, end = 0, counter = t.length(), minLen = Integer.MAX_VALUE, minStart = 0, size = s.length();
for (char c : s.toCharArray())
mp.put(c, 0);
for (char c : t.toCharArray()) {
if (mp.containsKey(c))
mp.put(c, mp.get(c) + 1);
else
return "";
}
while (end < size) {
if (mp.get(s.charAt(end)) > 0)
counter--;
mp.put(s.charAt(end), mp.get(s.charAt(end)) - 1);
end++;
while (counter == 0) {
if (end - begin < minLen) {
minStart = begin;
minLen = end - begin;
}
mp.put(s.charAt(begin), mp.get(s.charAt(begin)) + 1);
if (mp.get(s.charAt(begin)) > 0) {
counter++;
}
begin++;
}
}
if (minLen != Integer.MAX_VALUE) {
return s.substring(minStart, minStart + minLen);
}
return "";
}
}
function minWindow(s: string, t: string): string {
let n1 = s.length,
n2 = t.length;
if (n1 < n2) return '';
let need = new Array(128).fill(0);
let window = new Array(128).fill(0);
for (let i = 0; i < n2; ++i) {
++need[t.charCodeAt(i)];
}
let left = 0,
right = 0;
let res = '';
let count = 0;
let min = n1 + 1;
while (right < n1) {
let cur = s.charCodeAt(right);
++window[cur];
if (need[cur] > 0 && need[cur] >= window[cur]) {
++count;
}
while (count == n2) {
cur = s.charCodeAt(left);
if (need[cur] > 0 && need[cur] >= window[cur]) {
--count;
}
if (right - left + 1 < min) {
min = right - left + 1;
res = s.slice(left, right + 1);
}
--window[cur];
++left;
}
++right;
}
return res;
}
class Solution {
public:
string minWindow(string s, string t){
unordered_map<char, int> m;
int begin = 0, end = 0, minlen = INT_MAX, minStart = 0, size = s.size(), counter = t.size();
for (auto c: t)
m[c]++;
while (end < size) {
if (m[s[end]] > 0)
counter--;
m[s[end]]--;
end++;
while (counter == 0) {
if (end - begin < minlen) {
minStart = begin;
minlen = end - begin;
}
m[s[begin]]++;
if (m[s[begin]] > 0)
counter++;
begin++;
}
}
if (minlen != INT_MAX) {
return s.substr(minStart, minlen);
}
return "";
}
};
func minWindow(s string, t string) string {
ans := ""
m, n := len(s), len(t)
if m < n {
return ans
}
need := make([]int, 128)
for _, c := range t {
need[c] += 1
}
window := make([]int, 128)
i, cnt, mi := 0, 0, m+1
for j, c := range s {
window[c]++
if need[c] >= window[c] {
cnt++
}
for cnt == n {
if j-i+1 < mi {
mi = j - i + 1
ans = s[i : j+1]
}
c = rune(s[i])
if need[c] >= window[c] {
cnt--
}
window[c]--
i++
}
}
return ans
}