【算法】滑动窗口

滑动窗口

1.概念

滑动窗口是一类很常见的题型,最多见的就是子串问题,由于滑动窗口是一个连续的,因此很容易就是问知足条件的最大或者最小子串啊,这个条件就是不一样的地方,但万变不离其宗,滑动窗口就是一个窗口的移动。html

总之:子串+最值 --> 滑动窗口数组

滑动窗口有两大类指针

  • 固定长度的滑动窗口:窗口的大小是固定好的,这是其实分为了窗口造成和人窗口滑动两个过程,窗口造成就是要先让窗口达到要求的长度; 窗口滑动的过程在右边界长的时候,左边界也要跟着长,维持窗口长度不变;
  • 可变长度的滑动窗口:这也是遇到最多的,控制窗口移动的缘由不是长度,而是是否达到题目中某一条件,若是达到此条件,那右边界停下,左边界开始移动,试图去破坏这一条件,就是在这个过程当中不断的更新结果。

2.过程

  • 1.从题目中先整理出条件,常见的好比说子序列的和大于某值,子串中包含某些值,子串中出现了重复值,先把这些条件找出来,这就是用来移动窗口的依据;
  • 2.初始化left和right指针都为0,right指针从头走到尾,当不知足上面的条件时,right走,一直走到这个窗口知足上面咱们总结出来的条件了,停下;
  • 3.记录下咱们要的答案,好比最典型的问子串的最小长度啊啥的,记录下这时候咱们的right-left+1,这就是目前窗口的大小;
  • 4.右边走不动了那左边就得开始走了,移动左指针,每次移动都要把左指针的值给去除,由于咱们统计的结果只能是窗口里的结果,出去了天然就不要了,而后,每一次左指针的移动都要判断是否知足条件,好比要求子串和大于某一值,左边移动一步,减去这个值看还大于目标值吗,若是知足,更新咱们最终要的最小子串,由于这时候子串长度确定缩小了嘛,直到不知足条件为止;若是不知足,那左指针不用再动了,右指针能够开始动了,寻找下一个知足条件时停下来。
  • 5.就这样重复,右边动完左边动,左边动完右边再动;

总结:右边界要使窗口达到某一条件,左边界使窗口跳出这一条件code

3.模板

int left = 0, right = 0;
while(right < nums.length){
    result = result + nums[right]; 
    //更新窗口内数据;
    //将移入窗口的值添加进结果,这里就是不一样题目不一样要求;好比和,好比哈希表等;   
    while(判断是否达到条件){  //若是达到条件左窗口就要收缩了;
        res = Math.min(res, right-left+1); //只要知足条件每次都要更新答案;
        //更新窗口内数据;
        result = result - nums[left]; //左窗口的值从结果去除;
        left++; //左窗口移动;
    }
    right++;  //只要不知足条件右窗口移动;
}

其实,咱们的右边界就是在努力知足条件,找到一个可行解,而咱们的左边界呢,想让这个可行解更好一点,好比长度更短一下,是在寻找一个更好的最优解,可是极可能玩脱了不知足条件。htm

在套模板的时候咱们须要思考如下问题:blog

  • 1.当移动right,即加入结果的时候,须要更新哪些数据;
  • 2.到达什么条件时,窗口中止扩大,也就是右边界停下来,开始左边界移动,缩小窗口;
  • 3.当移动left,即移出结果的时候,须要更新哪些数据;
  • 4.要的最后答案应该在窗口扩大仍是窗口缩小时更新;

4.样例

3. 无重复字符的最长子串队列

209. 长度最小的子数组get

剑指 Offer 59 - I. 滑动窗口的最大值模板

424. 替换后的最长重复字符统计

5.体会

  • 要可以根据题目要求找到条件,由于条件是指挥咱们移动左窗口仍是右窗口的长官,不知足条件,右窗口移动; 知足条件,左窗口移动;
  • 要始终清楚左右两个边界都是不会回退的,都是朝着最后走的,不可能会出现往回走的时候;
  • 两个窗口不会同时移动,每次只有两个窗口中的一个移动。
  • 换种思路:咱们的窗口滑动其实就是一个双端队列。当不知足条件时,数组元素依次从队尾入队;当知足条件时,队首元素出队;因此有的时候去想象成一个队列,可能会更好的理解;
相关文章
相关标签/搜索