正题:滑动窗口
概述
TCP协议中,数据的发送方和接收方都会使用滑动窗口来控制数据的收发。
它有以下优点:
- 避免等待
- 流量控制
- 效率高
滑动窗口的使用避免了数据重复校验,在字符串匹配等场合有多应用。
思路
- 设置左右指针,指向窗口的左端和右端
- 右指针向右移动
- 右指针变化的同时,如果满足条件,左指针移动,缩小窗口
例题
leetcode 3.无重复字符的最长字串
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int ans=0;
int n=s.size();
if(n==0) return 0;
if(n==1) return 1;
unordered_map<char, int> ss;
int sptr=0;
int eptr=0;
while(eptr<n){
char c1=s[eptr++];
ss[c1]++;
while(ss[c1]>1){
char c2=s[sptr];
ss[c2]--;
sptr++;
}
ans=max(ans,eptr-sptr);
}
return ans;
}
};
leetcode 220.存在重复元素Ⅲ
思路:
set、滑动窗口
运用set内部排序的机制,滑动窗口主要就是要准确利用合适的数据结构;窗口就是边界的处理,内部所需要的东西,需要通过不同的数据结构来实现。
解析:
- eptr从小到大循环
- 窗口大小(即set.size())必须小于等于k,一旦比k大,左边界移一步(从set里擦除当前的sptr)
- 通过lower_bound()来找比nums[right]-t更大的数,如果找到了 就是true
- 如果循环完都没有找到,返回false
class Solution {
public:
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
int n=nums.size();
if(n==0||n==1) return false;
set<long >s1;
int sptr=0;
int eptr=0;
while(eptr<n){
if(eptr-sptr>k){
s1.erase(nums[sptr]);
sptr++;
}
if(s1.lower_bound((long long )nums[eptr]-t)!=s1.end()&&(*(s1.lower_bound((long long)nums[eptr]-t))-nums[eptr]<=t))
return true;
s1.insert(nums[eptr]);
eptr++;
}
return false;
}
};