题意
题解
方法一:滑动窗口
在滑动窗口类型的问题中都会有两个指针,一个用于「延伸」现有窗口的 r
指针,和一个用于「收缩」窗口的 l
指针。在任意时刻,只有一个指针运动,而另一个保持静止。我们在s
上滑动窗口,通过移动 r
指针不断扩张窗口。当窗口包含 t
全部所需的字符后,如果能收缩,我们就收缩窗口直到得到最小窗口。
时间复杂度:O(|S|+|T|),这里|S|表示字符串S的长度,|T|表示字符串T的长度
空间复杂度:O(|S|+|T|)
相同类型的题还有LeetCode中的3、209、424、438、567题
class Solution {
public:
string minWindow(string s, string t) {
int sLen = s.size();
int tLen = t.size();
if (sLen == 0 || tLen == 0 || sLen < tLen) {
return "";
}
int distance = 0, left = 0, right = 0;
int minLen = sLen + 1, minLeft = 0;
int winFreq[128];
int tFreq[128];
memset(winFreq, 0, 128 * sizeof(int));
memset(tFreq, 0, 128 * sizeof(int));
for (const char& c : t) {
tFreq[c]++;
}
while (right < sLen) {
if (tFreq[s[right]] == 0) {
right++;
continue;
}
if (winFreq[s[right]] < tFreq[s[right]]) {
distance++;
}
winFreq[s[right]]++;
right++;
while (distance == tLen) {
if (right - left + 1 < minLen) {
minLen = right - left + 1;
minLeft = left;
}
if (tFreq[s[left]] == 0) {
left++;
continue;
}
if (winFreq[s[left]] == tFreq[s[left]]) {
distance--;
}
winFreq[s[left]]--;
left++;
}
}
return minLen == sLen + 1 ? "" : s.substr(minLeft, minLen);
}
};
另一种解法
class Solution {
public:
unordered_map <char, int> ori, cnt;
bool check() {
for (const auto &p: ori) {
if (cnt[p.first] < p.second) {
return false;
}
}
return true;
}
string minWindow(string s, string t) {
for (const auto &c: t) {
++ori[c];
}
int l = 0, r = -1;
int len = INT_MAX, ansL = -1, ansR = -1;
while (r < int(s.size())) {
if (ori.find(s[++r]) != ori.end()) {
++cnt[s[r]];
}
while (check() && l <= r) {
if (r - l + 1 < len) {
len = r - l + 1;
ansL = l;
}
if (ori.find(s[l]) != ori.end()) {
--cnt[s[l]];
}
++l;
}
}
return ansL == -1 ? string() : s.substr(ansL, len);
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/minimum-window-substring/solution/zui-xiao-fu-gai-zi-chuan-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。