目录
知识框架
No.0 筑基
请先学习下知识点,道友!
题目知识点大部分来源于此:题目例题大部分来源于此:
所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
在暴力解法中,是一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环 完成了一个不断搜索区间的过程。
那么滑动窗口如何用一个for循环来完成这个操作呢?
首先要思考 如果用一个for循环,那么应该表示 滑动窗口的起始位置,还是终止位置?
如果只用一个for循环来表示 滑动窗口的起始位置,那么如何遍历剩下的终止位置?
此时难免再次陷入 暴力解法的怪圈。
所以 只用一个for循环,那么这个循环的索引,一定是表示 滑动窗口的终止位置。
那么问题来了, 滑动窗口的起始位置如何移动呢?
No.1 字符串滑动窗口
题目来源:LeetCode-3. 无重复字符的最长子串
题目描述:
题目思路:
题目代码:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int len = s.size();
map<char,int>mp;
int ans=0;
for(int i=0, j=0;j<len;j++){
//先判断右边指向的是否在窗口内;
//在里面
if( mp[s[j] ]==1){
while(mp[s[j]]==1){
mp[s[i] ]=0;
i++;
}
}
mp[s[j] ]=1;
ans=max(ans,j-i+1);
}
return ans;
}
};
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if(s.size() == 0) return 0;
unordered_set<char> lookup;
int maxStr = 0;
int left = 0;
for(int i = 0; i < s.size(); i++){
while (lookup.find(s[i]) != lookup.end()){
lookup.erase(s[left]);
left ++;
}
maxStr = max(maxStr,i-left+1);
lookup.insert(s[i]);
}
return maxStr;
}
};
No.2 数组滑动窗口
题目来源:LeetCode-209-长度最小的子数组
题目描述:
题目思路:
滑动窗口的题目;
题目代码:
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int result = INT32_MAX;
int sum = 0; // 滑动窗口数值之和
int i = 0; // 滑动窗口起始位置
int subLength = 0; // 滑动窗口的长度
for (int j = 0; j < nums.size(); j++) {
sum += nums[j];
// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
while (sum >= s) {
subLength = (j - i + 1); // 取子序列的长度
result = result < subLength ? result : subLength;
sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
}
}
// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
return result == INT32_MAX ? 0 : result;
}
};
题目来源:蓝桥杯-第十四届模拟-附近最小
题目描述:
题目思路:
题目代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e7 + 10;
int q[N];int a[N];
int b[N];int n, k;
int sum;
/*
* 滑动窗口是从寻找到的位置i开始算长度的
* 而这个是从i-k开始算的,所以题目可以转换为
* 原数组n+2k个元素,然后从1开始遍历,滑动窗口长度为2*k+1
* 记得初始化前k个元素和后k个元素极大值如1e18,这样就可以防止初值0造成影响
*/
void min_q()
{
int h = 1, t = 0;
int len = 2 * k + 1;
for (int i = 1; i <= n+2*k; i++)
{
while (h <= t && q[h] + len <= i)h++;
while (h <= t && b[i] < b[q[t]])t--;
q[++t] = i;
if (i >= len)
{
cout << b[q[h]] << " ";
}
}
cout << endl;
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)cin >> a[i];
cin >> k;
for (int i = 1; i <= k; i++)b[i] = 1e18;
for (int i = k + n + 1; i <= n + 2 * k; i++)b[i] = 1e18;
for (int i = k + 1; i <= k + n; i++)b[i] = a[i - k];
//for (int i = 1; i <= n + 2 * k; i++)cout << b[i] << " ";
//cout << endl;
min_q();
return 0;
}