前言
一、算法应用场景
关键词:
二、滑动窗口代码模板
说明:理论上你可以设计两端都开或者两端都闭的区间,但设计为左闭右开区间是最方便处理的。因为这样初始化 left = right = 0
时区间 [0, 0)
中没有元素,但只要让 right
向右移动(扩大)一位,区间 [0, 1)
就包含一个元素 0
了。如果你设置为两端都开的区间,那么让 right
向右移动一位后开区间 (0, 1)
仍然没有元素;如果你设置为两端都闭的区间,那么初始区间 [0, 0]
就包含了一个元素。这两种情况都会给边界处理带来不必要的麻烦。
给出了两个滑动窗口的模板,并且又给出了求最长/最短/固定时的模板,并不是说有五个模板,其实后三个模板是嵌套在前两个中的,即后三个模板需要关注的是内层while的条件(窗口固定情况下时也可用while,但是if即可满足)以及最终结果result的更新位置。
希望你写滑动窗口时能有三问:
1、什么时候应该扩大窗口?
2、什么时候应该缩小窗口?
3、什么时候应该更新答案?
滑动窗口 + 变量计数模板
class Solution { public int slidingWindow(int[] nums, int k) { //数组/字符串长度 int n = nums.length; //双指针,表示当前遍历的区间[left, right),左闭右开 int left = 0, right = 0; //定义变量统计 子数组/子区间 是否有效 int sum = 0; //定义变量动态保存最大 求和/计数 int res = 0; //右指针遍历到数组尾 while (right < n) { //增加当前右指针对应的数值 sum += nums[right]; //增加窗口,移动右指针,实现右开效果 right++; //当在该区间内 sum 超出定义范围 while (sum > k) { //先将左指针指向的数值减去 sum -= nums[left]; //缩小窗口 left++; } //到 while 结束时,我们找到了一个符合题意要求的 子数组/子串 res = Math.max(res, right - left); } return res; } }
滑动窗口 + 哈希表存储模板
class Solution { public String slidingWindow(String s, String t) { //创建两个哈希表,分别记录 [窗口] 和 [需要的] Map<Character, Integer> window= new HashMap<>(); Map<Character, Integer> need= new HashMap<>(); //创建 [双指针] 和 [有效数量] int left = 0, right = 0; int valid = 0; //外层循环,供右指针遍历 while(right < s.length()){ //创建临时 c 字符,是移入 窗口 内的字符 char c = s.charAt(right); //增大窗口 right++; //进行窗口一系列逻辑更新 ... /*** debug 输出的位置 ***/ //System.out.println("window: [" + left + "," + right + ")"); //判断左指针是否要右移即窗口收缩:有效数量足够满足条件 /* 可能是规定的窗口大小超出了,可能是有效值数量达成了 1. while(valid == need.size()) 2. while(right - left >= s1.length()) */ while(windows need shrink){ // 创建 d 是要移除窗口的字符 char d = s.charAt(left); //缩小窗口 left++; //进行窗口一系列逻辑更新 ... } } } }
寻找最长模板(while为窗口不满足条件,结果result在外部更新)
初始化 left,right,window,result
while("右指针没有到结尾"){
窗口扩大,加入right对应元素,更新当前window
right++;(right右移,起到左闭右开的效果,[left,right))
while("window不满足要求"){
窗口缩小,移除left对应元素,left右移
}
更新最优结果result
}
返回result
寻找最短模板(while为窗口满足条件,结果result在内部更新)
初始化 left,right,window,result
while("右指针没有到结尾"){
窗口扩大,加入right对应元素,更新当前window
right++;(right右移,起到左闭右开的效果,[left,right))
while("window满足要求"){
更新最优结果result
窗口缩小,移除left对应元素,left右移
}
}
返回result
窗口大小固定模板
初始化 left,right,window,result while("右指针没有到结尾"){ 窗口扩大,加入right对应元素,更新当前window right++;(right右移,起到左闭右开的效果,[left,right)) if("window达到固定值(right-left==target_length)"){ if(满足条件){ 处理结果; } 窗口缩小,移除left对应元素,left右移 } } 返回result
原文链接:https://www.cnblogs.com/Co3y/p/17275580.html
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:滑动窗口总结 - Python技术站