滑动窗口总结

前言

滑动窗口是双指针的一种特例,可以称为左右指针,在任意时刻,只有一个指针运动,而另一个保持静止。滑动窗口路一般用于解决特定的序列中符合条件的连续的子序列的问题。
好处:时间复杂度 O(n^2) ---> O(n)

一、算法应用场景

关键词:

1.满足XXX条件(计算结果、出现次数、同时包含)
2.最长/最短/或最值
3.子串/子数组/子序列
最最最重要的提示点是:必须是连续的,否则不可以用滑动窗口

二、滑动窗口代码模板

说明:理论上你可以设计两端都开或者两端都闭的区间,但设计为左闭右开区间是最方便处理的。因为这样初始化 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技术站

(0)
上一篇 2023年4月17日
下一篇 2023年4月17日

相关文章

  • Python数据结构之栈详解

    Python数据结构之栈详解 什么是栈? 栈(stack)是一种数据元素只能在一端进行插入和删除操作的线性表。 栈的特点是后进先出,即在一个非空栈中,最后放入的元素最先被取出。 栈的操作 栈操作的基本有两个: push(elem):插入一个新的元素elem到栈中。 pop():弹出栈顶的元素,并返回这个被弹出元素的值。 此外还有一个用于查询栈顶元素的操作: …

    数据结构 2023年5月17日
    00
  • python使用三角迭代计算圆周率PI的方法

    下面是详细讲解“Python使用三角迭代计算圆周率PI的方法”的完整攻略。 1. 什么是三角迭代计算圆周率PI的方法? 三角迭代计算圆周率PI的方法是一种使用三角函数计算圆周率的方法。该方法基于圆的周长与直径比值为PI,通过计算正多边形的周长和直径的比值,逐步逼近圆的周长与直径的比值,从而得到圆周率的近似值。 2. Python使用三角迭代计算圆周率PI的方…

    python 2023年5月14日
    00
  • 详解动态规划算法原理与使用方法

    动态规划算法 什么是动态规划算法? 动态规划是一种算法思想,可以用来解决多阶段决策问题,通常具有以下两个特点: 最优化原理:如果问题的最优解包含子问题的最优解,那么可通过自底向上的方式动态地解决问题。 无后效性:子问题的解一旦确定了,就不会受到在这之后、包含它的更大的问题的求解策略的影响。 动态规划算法使用方法 确定状态:动态规划所涉及到的状态一般具有两个意…

    算法 2023年3月27日
    00
  • Java 数据结构与算法系列精讲之二叉堆

    Java 数据结构与算法系列精讲之二叉堆 什么是二叉堆? 二叉堆是一种基于完全二叉树的数据结构,它分为大根堆(MaxHeap)和小根堆(MinHeap)。大根堆的每个节点的值都大于(或等于)它的子节点的值,小根堆的每个节点的值都小于(或等于)它的子节点的值。 二叉堆的操作 二叉堆主要有以下几种操作: 插入元素:将元素插入到堆的最后一个叶子节点,然后通过上滤操…

    数据结构 2023年5月17日
    00
  • js实现无限层级树形数据结构(创新算法)

    要实现无限层级树形数据结构,可以使用递归算法来解决。以下是该过程的详细攻略: 步骤1:准备数据 为了演示无限层级树形结构,我们需要准备一组具有父子关系的数据。数据可以是任何格式,例如在子对象节点下添加一个名为children的数组即可。 例如,假设我们有以下数据: const data = [ { id: 1, name: "Node 1&quot…

    数据结构 2023年5月17日
    00
  • Python数据结构与算法中的队列详解(1)

    Python数据结构与算法中的队列详解(1) 队列是一种常见的数据结构,它遵循先进先出(FIFO)的原则。在Python中,我们可以使用列表来实现队列。本文将介绍队列的基本概念、实现方式和常见操作。 队列的基本概念 队列是一种线性数据结构,它支持两个基本操作:入队和出队。入队操作将一个元素添加到队列的末尾,出队操作将队列的第一个元素删除并返回。队列的另一个重…

    python 2023年5月14日
    00
  • Python编程快速上手——强口令检测算法案例分析

    下面是详细讲解“Python编程快速上手——强口令检测算法案例分析”的完整攻略,包括算法原理、Python实现和两个示例说明。 算法原理 强口令检测法是一种基于规则的算法,其主要思想是通过一系列规则来判断口令是否强壮。强口令通常包括大小写字母、数字和特殊字符,长度较长,且不易被猜测。强口令检测算法的实现过程如下: 判断口令长度是否符合要求。 判断口令是否包含…

    python 2023年5月14日
    00
  • C++如何实现BitMap数据结构

    下面我将详细讲解C++如何实现BitMap数据结构的完整攻略,包含以下几个方面: 什么是BitMap数据结构 如何使用C++实现BitMap数据结构 BitMap数据结构的应用示例说明 1. 什么是BitMap数据结构 BitMap数据结构也叫位图,是一种非常简单而高效的数据结构,它主要是用来对大量数字进行存储和操作的。所谓BitMap,就是将一个数字序列通…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部