- 76. 最小覆盖子串 困难
- 239. 滑动窗口最大值 困难
- 438. 找到字符串中所有字母异位词 中等

解法1: 滑动窗口
string minWindow(string s, string t) {
vector<int> need(128, 0)
int count = 0
for (char c : t) {
need[c]++
}
count = t.length()
int l = 0, r = 0, start = 0, size = INT_MAX
while (r < s.length()) { // 遍历字符串s
char c = s[r]
if (need[c] > 0) {
count--
}
need[c]--
if (count == 0) { // 当窗口中已经包含所需的全部字符时
while (l < r && need[s[l]] < 0) { // 缩减窗口左边界,释放不需要的字符
need[s[l]]++
l++
}
if (r - l + 1 < size) { // 更新最小子串的信息
size = r - l + 1
start = l
}
need[s[l]]++
l++
count++
}
r++
}
return size == INT_MAX ? "" : s.substr(start, size)
}

解法1: 优先队列
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
int n = nums.size();
priority_queue<pair<int, int>> q;
for (int i = 0; i < k; ++i) {
q.emplace(nums[i], i);
}
vector<int> ans = {q.top().first};
for (int i = k; i < n; ++i) {
q.emplace(nums[i], i);
while (q.top().second <= i - k) {
q.pop();
}
ans.push_back(q.top().first);
}
return ans;
}

解法2: 单调队列
- 初始化双端队列queue, 和结果数组res
- 数组长度为nums.size() - k + 1
- 算法的核心思想是使用一个
双端队列来维护当前滑动窗口中的元素的索引,确保队列中的元素按照从前到后递减的顺序排列

vector<int> maxSlidingWindow(vector<int>& nums, int k) {
if (nums.size() == 0 || k == 0) return {};
deque<int> deque;
vector<int> res(nums.size() - k + 1);
for (int j = 0, i = 1 - k; j < nums.size(); i++, j++) {
if (i > 0 && deque.front() == nums[i - 1]) {
deque.pop_front();
}
while (!deque.empty() && deque.back() < nums[j]) {
deque.pop_back();
}
deque.push_back(nums[j]);
if (i >= 0) {
res[i] = deque.front();
}
}
return res;
}


解法1: 滑动窗口
class Solution {
public:
vector<int> findAnagrams(string s, string p)
{
vector<int> res
int sLen = s.size()
int pLen = p.size()
//如果子串更长则直接返回
if(pLen > sLen)
{
return vector<int>()
}
vector<int> sCount(26)
vector<int> pCount(26)
//记录p和s的前几个字符以及数量
for(int i = 0
{
sCount[s[i] - 'a']++
pCount[p[i] - 'a']++
}
if(sCount == pCount)
{
res.push_back(0)
}
for(int i = pLen
{
// 每次循环添加尾部字符
sCount[s[i] - 'a']++
// 每次循环除去首个字符
sCount[s[i - pLen] - 'a']--
//每次循环判断一次是否相同
if(sCount == pCount)
{
res.push_back(i - pLen + 1)
}
}
return res
}
}

解法2: 优化后滑动窗口
- 不再分别统计滑动窗口和字符串 p 中每种字母的数量,而是统计滑动窗口和字符串 p 中每种字母数量的差;并引入变量 differ 来记录当前窗口与字符串 p 中数量不同的字母的个数,并在滑动窗口的过程中维护它。
- 在判断滑动窗口中每种字母的数量与字符串 p 中每种字母的数量是否相同时,只需要判断 differ 是否为零即可
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
int sLen = s.size(), pLen = p.size()
if (sLen < pLen) {
return vector<int>()
}
vector<int> ans
vector<int> count(26)
for (int i = 0
++count[s[i] - 'a']
--count[p[i] - 'a']
}
int differ = 0
for (int j = 0
if (count[j] != 0) {
++differ
}
}
if (differ == 0) {
ans.emplace_back(0)
}
for (int i = 0
if (count[s[i] - 'a'] == 1) { // 窗口中字母 s[i] 的数量与字符串 p 中的数量从不同变得相同
--differ
} else if (count[s[i] - 'a'] == 0) { // 窗口中字母 s[i] 的数量与字符串 p 中的数量从相同变得不同
++differ
}
--count[s[i] - 'a']
if (count[s[i + pLen] - 'a'] == -1) { // 窗口中字母 s[i+pLen] 的数量与字符串 p 中的数量从不同变得相同
--differ
} else if (count[s[i + pLen] - 'a'] == 0) { // 窗口中字母 s[i+pLen] 的数量与字符串 p 中的数量从相同变得不同
++differ
}
++count[s[i + pLen] - 'a']
if (differ == 0) {
ans.emplace_back(i + 1)
}
}
return ans
}
}
