算法思想-滑动窗口思想
在解Leetcode题的时候,遇到了几个新的算法思想,这个系列文章就把Leetcode中的一些算法思想做一些整理,包括老生常谈的动态规划,也包括我最新接触的滑动窗口思想,并查集等,另外,遇到新的题目的时候也会在这里做一些整理。
起源-计算机网络协议
在介绍滑动窗口思想之前,首先介绍这个算法思想的由来,是一种TCP网络协议-滑动窗口协议,其实在大学学计算机网络的时候,自己可能并没有对这个协议有太多的印象,也许是当时用的太少,工作之后这方面涉及的也比较少,所以在整理这篇文章之前,我先补了一下计算机网络知识-滑动窗口协议。
一条TCP连接的双方主机都为该连接设置了接收缓存。当该TCP连接收到正确按序字节后,它就把数据放入缓存中,应用进程从缓存中读取数据,是异步的,因此不保证所有数据都在第一时间被读取,当发送方发送的数据过多或者过快的时候,就会造成缓存不够用,也就是缓存溢出。
TCP通过让发送方维护一个接收窗口的变量来提供流量控制服务,以消除缓存溢出的可能性,接收窗口用于告诉发送方接收方还有多少空间,做一个比喻,也就是说,发送信息方相当于做饼的人,接收方相当于吃饼的人,接收方通过一个变量告诉发送方,我还能吃多少饼,显然这个变量是可以变化的。
(以上部分内容出自《计算机网络-自顶向下方法》 ((美) James F Kurose,(美)Keith W Ross)著)
滑动窗口思想(算法)
比起滑动窗口算法这种比较正式的算法叫法,我更愿意把它称作一种思想,因为他并不是像并查集,红黑树那样使用固定的数据结构去解决问题的算法,它更像动态规划那种,是一种思想,或者可以称为解决问题的思路,在我遇到的例子当中,并没有哪一个题目是必须用这个算法来解决的,它是一种优化的思想,用于解决一个特定大小的字符串或数组上进行操作,用于降低循环的嵌套层次,也就是降低算法复杂度。总结一下就是“请找到满足xx的最x的区间(子串、子数组)的xx”这类问题都可以用滑动窗口思想来优化。
具体实例
A的最大长度是20000,因此,不能使用枚举方案了,我们考虑用滑动窗口来解决
class Solution {
public:
int maxTurbulenceSize(vector<int>& A) {
int ans = 1, count = 1;
bool flag;
for(int i=1; i<A.size();)
{
count = 1;
if(A[i] != A[i-1])
{
flag = (max(A[i], A[i-1]) == A[i]);
while(i<A.size() && flag == (max(A[i], A[i-1]) == A[i]) && (A[i] != A[i-1]))
{
count++;
flag = !flag;
i++;
}
if(count > ans)
{
ans = count;
}
}
else
{
i++;
}
}
return ans;
}
};
窗口的起点从i-1开始,每次先和相邻的点做比较,如果不相等,窗口进一步向后滑动,如果继续不等,判断是否和下一个flag相等,窗口继续滑动,直到不满足条件为止。