概述
题目连接
- 注意:要求时间复杂度为 O ( n ) O(n) O(n)
分析
要求 O ( n ) O(n) O(n),并且结果也是一个连续的字符串,所以考虑使用双指针进行区间搜索
思路
- 滑动窗口思路?
- 首先固定左边界,然后右边界开始向右滑动向窗口中加入元素
- 当所有所需的字符加入窗口后,此时右边界是最小的,但是左边界不一定,所以可以移动左边界,将字符移出去的同时继续使窗口满足条件
- 直到因为左边界移动导致该窗口不满足条件,则停止移动左边界,继续移动右边界
- 重复以上行为,直到右边界到达最后位置
代码
class Solution {
public:
string minWindow(string s, string t) {
// 前置处理,用来判断窗口内是否包含所有字符
unordered_map<char,int> unordered_map_char_to_int;
for (auto p : t)
++unordered_map_char_to_int[p];
int size_s = s.size(), size_t = t.size();
int l = 0; // 记录目前窗口的左边位置
int min_l = 0; // 记录之前窗口的左边位置
int min_size = size_s + 1; // 记录窗口大小
int count = 0; // 记录是否包含所有字符
// 窗口左边界不动,右边界滑动,直到包含所有所需字符后,再移动左边界目的是减小窗口
for(int r = 0; r < size_s; ++r) {
if (unordered_map_char_to_int[s[r]]-- > 0) { // >0,说明t中的字符被包含
++count;
while (count == size_t) { // 窗口内包含t的所有字符
if (r - l + 1 < min_size) { // 比较窗口大小
min_l = l; // 记录新窗口
min_size = r - l + 1;
}
if (++unordered_map_char_to_int[s[l]] > 0) { // 移动窗口
// 注意大小判断: >0说明所需某个字符已经不存在窗口中,此时需要右侧开始移动
--count;
}
++l; // 移动现在窗口左边界,尽可能减小窗口
}
}
}
return min_size > size_s ? "" : s.substr(min_l, min_size);
}
};
- 尽管
循环里面有for
循环,但是最坏情况是 O ( 2 n ) O(2n) O(2n)while