leetcode_ 76 最小覆盖子串
1. 题意
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
2. 题解
这道题目和438. 找到字符串中所有字母异位词
做法基本一致。
2.1 不定滑窗+每次检查
一种方法是使用不定滑动窗口,
检查当前元素是否能入窗口。
在检查窗口是否满足覆盖条件。
时间复杂度O(n+∣Σ∣m)O(n+|\Sigma| m)O(n+∣Σ∣m)
空间复杂度O(∣Σ∣)O(|\Sigma|)O(∣Σ∣)
∣Σ∣|\Sigma|∣Σ∣为字符集的大小,这里是大小写字母个数总和525252。
需要注意处理没有覆盖子串的情况。
class Solution {
public:string minWindow(string s, string t) {int slen = s.size();int tlen = t.size();array<int, 52> ht;array<int, 52> hs;auto to_idx = [](char c) {if ( c >= 'a' && c <= 'z')return c - 'a';return c - 'A' + 26;};for (auto c: t)ht[ to_idx(c)]++;int start = 0;int len = INT_MAX;int l = 0;for (int r = 0; r < slen; ++r) {hs[ to_idx(s[r]) ]++;while (l <= r && (hs[ to_idx(s[l]) ] > ht[ to_idx(s[l]) ]) ) {--hs[to_idx(s[l])];++l;}bool ok = true;for (int i = 0; i < 52; ++i)if ( ht[i] != 0 && ht[i] > hs[i]) {// cout << i << " " << ht[i] << " " << endl;ok = false;break;}// cout << "lbound: " << l << " rbound " << r << endl;// cout << "ok: " << ok << endl;if (ok && (r - l + 1) < len) {len = r - l + 1;start = l;}}return len == INT_MAX ? "" : s.substr(start, len);}
};
2.2 不定滑窗+种类差值判断
每次都要花O(∣Σ∣)O(|\Sigma|)O(∣Σ∣)的时间去判断当前的窗口太复杂了,
有没有什么方法可以优化为O(1)O(1)O(1)呢?有的兄弟,有的。
可以用hththt直接表示当前窗口和子串之间的差值
ht[i]=cnt[t]−cnt[s]ht[i] = cnt[t]-cnt[s]ht[i]=cnt[t]−cnt[s],再用diffdiffdiff表示没有覆盖的字符串的种类。
当ht[s[l]]<0ht[s[l]]<0ht[s[l]]<0时,表示当前窗口有多余,就可以不断缩小窗口大小。
当ht[s[r]]==0ht[s[r]]==0ht[s[r]]==0时,说明有一种字符满足条件了,就可以−−diff--diff−−diff了。
这种做法在438. 找到字符串中所有字母异位词
的官解中是有的。
时间复杂度O(n+m)O(n+m)O(n+m)
空间复杂度O(∣Σ∣)O(|\Sigma|)O(∣Σ∣)
class Solution {
public:string minWindow(string s, string t) {int slen = s.size();int tlen = t.size();array<int, 52> ht;auto to_idx = [](char c) {if ( c >= 'a' && c <= 'z')return c - 'a';return c - 'A' + 26;};int diff = 0;for (auto c: t)ht[ to_idx(c)]++;for (int i = 0; i < 52; ++i)if (ht[i])diff++;int start = 0;int len = INT_MAX;int l = 0;for (int r = 0; r < slen; ++r) {int ridx = to_idx(s[r]);if ( ht[ ridx ] == 1) {diff--;}ht[ridx]--;while ( l <= r && ht[ to_idx(s[l]) ] < 0) {ht[ to_idx(s[l]) ]++;l++;}if ( len > (r - l + 1) && diff == 0) {len = r - l + 1;start = l;}}// 特别处理len == INT_MAX的情况return len == INT_MAX ? "" : s.substr(start, len);}
};
3. 参考
0x3f