【算法】滑动窗口

目录

基本思想

应用场景

应用实例

总结


基本思想

**滑动窗口,**也叫尺取法,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果,可以用来解决一些查找满足一定条件的连续区间的性质(长度等)的问题。

在暴力解法中,是一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环 完成了一个不断搜索区间的过程。这样的操作在面对极大的数据量是,效率极低。

而滑动窗口法是维护两个指针来进行操作,通常情况下时间复杂度为O(N)。

应用场景

  1. 一般给出的数据结构是数组或者字符串
  2. 求取某个子串或者子序列最长最短等最值问题或者求某个子序列的和等于目标值时

应用实例

以Leetcode上的一个题目为例子:

长度最小的子数组

这个题目的暴力解法当然就是两个for循环,然后不断的寻找符合条件的子序列,时间复杂度很明显是O(n^2),这样的解法在Leetcode上也会超时。

那么我们可以试着用滑动窗口的方法来看看。

滑动窗口的方法通过一个for循环来达到目的,那问题又来了,for循环表示的是窗口的起始位置,还是终止位置?

我们可以先假设for循环表示的窗口的起始位置,那么我们又该如何遍历数组?如果再设置一个循环,那这个方法就和暴力解法无异了。

所有,for循环表示的是滑动窗口的终止位置,我们也可以通过这个题目来验证一下。

以题目中的数组nums=[2,3,1,2,4,3],目标和target=7为例,来模拟一下滑动窗口的运行过程:

根据子序列和的大小不断调整滑动窗口的大小,当和小于target时,end++;当和大于等于target时,start++,在移动过程中,当sum==target时,记录并不断更新L的值 ,使得最后得到满足其和 ≥ target长度最小连续子数组

代码如下:

cpp 复制代码
int minSubArrayLen(int target, int* nums, int numsSize) {
    int start=0;
    int end=0;
    int sum=0;
    int suml=0;
    int result=numsSize+1;
    for(end;end<numsSize;end++)
    {
        sum+=nums[end];
        while(sum>=target)
        {
            suml=end-start+1;
            result=fmin(result,suml);
            sum-=nums[start];
            start++;
        }
    }

    return result==numsSize+1?0:result;
}

水果成篮

这个题目的大致意思就是要使得窗口里面只有两种数并且长度最长,可以使用滑动窗口来解决。

  1. 可以考虑用哈希表(数组模拟)保存窗口中数字出现的次数;
  2. end指针每次向右移动,如果是没有出现的数字,则cnt++;
  3. 如果cnt>2,则说明窗口中出现了三个数,此时需要收缩窗口;
  4. 直到窗口中的数字出现次数减到0(hash[fruits[start]]--,start++),cnt--;
  5. 然后重复上述流程。

代码如下:

cpp 复制代码
int totalFruit(int* fruits, int fruitsSize) {
int hash[100001]={0};

    int start=0;
    int end=0;
    int max=0;
    int cnt=0;
    for(end;end<fruitsSize;end++)
    {
        if(hash[fruits[end]]==0)
        {
            cnt++;
        }
        hash[fruits[end]]++;
        if(cnt<=2)
        {
            max=fmax(max,end-start+1);
        }
        while(cnt>2&&start<fruitsSize)
        {
            hash[fruits[start]]--;
            if(hash[fruits[start]]==0)
            {
                cnt--;
            }
            start++;
        }
    }
    return max;
}

总结

滑动窗口法可以用来解决一些查找满足一定条件的连续区间的性质(长度等)问题 ,实际上就是双指针法,两个指针都从原点开始,一前一后,遇到不同的条件,移动不同的指针,最终得到问题的答案。

相关推荐
前端小L17 小时前
图论专题(十九):DAG上的“关键路径”——极限规划「并行课程 III」
算法·矩阵·深度优先·图论·宽度优先
scx2013100417 小时前
20251116 树状DP总结
算法·深度优先·图论
Aspect of twilight18 小时前
LeetCode华为大模型岗刷题
python·leetcode·华为·力扣·算法题
别动哪条鱼18 小时前
MP4转AAC转换器C++
c++·ffmpeg·音视频·aac
2301_8079973818 小时前
代码随想录-day47
数据结构·c++·算法·leetcode
李日灐18 小时前
手搓简单 string 库:了解C++ 字符串底层
开发语言·c++
Elias不吃糖18 小时前
LeetCode每日一练(3)
c++·算法·leetcode
小龙报18 小时前
《算法通关指南数据结构和算法篇(2)--- 链表专题》
c语言·数据结构·c++·算法·链表·学习方法·visual studio
艾莉丝努力练剑19 小时前
【优选算法必刷100题】第031~32题(前缀和算法):连续数组、矩阵区域和
大数据·人工智能·线性代数·算法·矩阵·二维前缀和
醉颜凉19 小时前
环形房屋如何 “安全劫舍”?动态规划解题逻辑与技巧
c语言·算法·动态规划