【滑动窗口】滑窗模板,在小小的算法题里滑呀滑呀滑

news2024/11/26 22:26:05

首先大家先喊出我们的口号:跟着模板搞,滑窗没烦恼!

 

一.什么是滑动窗口?

滑动窗口算法是双指针算法的一种特定化的算法模型,常用于在特定的条件下求最大或者最小的字符串,特定的数组,以及字符序列等相关问题,使用滑动窗口的目的也很简单:使原本需要使用双循环嵌套来解决的问题通过双指针来解决,从而使时间复杂度大大降低(一般而言是将O(n^2)的时间复杂度降至O(n))

二.滑动窗口的框架和模板

做滑动窗口题目的痛点

很多小伙伴在刷LeetCode题目时可能会有这样的感觉:好像这个题是使用滑动窗口来进行解决,怎么解决呢?接着列出了left和right两个指针,之后就不知所措了,这主要对整个滑动窗口算法的执行流程很陌生而导致的,除此之外,即使我们看了题解,知道了解决这个题的整体思路,当我们过两天再来看这个题目的时候,由于缺失了对滑动窗口算法的某些特定步骤的启发,我们还是对这个题目不知所措,经过大佬们们不断的刷题和对滑动窗口算法的总结,滑动窗口的算法模型应运而生~

使用滑动窗口框架的优势

滑动窗口框架的优势我们可以从以下几点进行说明:1.使用滑动窗口的框架,能降低整道题目的难度,在特定的难点能够给我们带来启发2.使用滑动窗口的框架,能够使我们将更多的精力放到核心思想的思考上,提高我们刷题的效率。3.使用模板进行开发,当我们回头再来看这个题目时,记忆也会直接锁定到题目中的难点,记忆会更加深刻。

滑动窗口的框架模板如下

最长模板

模板的实现思路如下:我们在使用滑动窗口的模板时,对求最长和最短的字符序列或者字符串给出两种不同的实现思路以及模板代码:
求最长相关的实现思路:

左右指针(LR)在起始位置,R指针逐步向右循环滑动,在每次滑动的过程中,如果滑动窗口内的元素满足滑动窗口的需求,R指针不断向右滑动扩大窗口,并不断更新最优结果;如果窗内元素不满足条件,L指针不断向右缩小窗口,在此过程中并不断更新结果,直到R到达结尾

初始化 left,right,result,bestResult
while("右指针没有到结尾"){
    窗口扩大,加入right对应元素,更新当前result
    while("result不满足要求"){
        窗口缩小,移除left对应元素,left右移
    }
    更新最优结果bestResult
    right++;
}
返回bestResult

最短模板

实现思路:

左右指针(LR)初始在起始点,R逐步向右滑动,在每次滑动的过程中,如果窗口内的元素满足条件,L向右缩小窗口,并不断更新最小的结果,如果窗口内的元素不满足条件,R不断向右扩大窗口,直到R到达字符串的结尾

初始化 left,right,result,bestResult
while("右指针没有到结尾"){
    窗口扩大,加入right对应元素,更新当前result
    while("result满足要求"){
        更新最优结果bestResult
        窗口缩小,移除left对应元素,left右移
    }
    right++;
}
返回bestResult

三.实战分析

3.1 和大于等于 target 的最短子数组

题目描述

解题思路

按照我们上面给出模板的逻辑,我们给出以下的解题思路:定义两个指针(LR),由于这个题目求的是最短的子数组,套用上面的模板,当不满足条件的时候R不断向右移动,当满足条件之后L指针向右移动不断缩小窗口中元素的数量,最终求得所求数组数量的最小值

示例代码

我们给出实例代码:

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        //设置最小个数
        int count=0;
        int left=0;
        int right=0;
        int sum=0;
        int minLength=Integer.MAX_VALUE;
        //进行遍历
        while(right<nums.length){
            sum+=nums[right];
            count++;
            while(sum>=target){
                if(count<minLength){
                    minLength=count;
                }
                sum-=nums[left];
                 left++;
                count--;
            }
            right++;
        }
        if(minLength==Integer.MAX_VALUE){
            return 0;
        }
        return minLength;
    }
}

3.2 最小覆盖子串

题目描述

解题思路

大家不要被这道试题的难度吓到,我们要始终相信:跟着模板搞,滑窗没烦恼!ok,接下来讲述我们这道题的解题思路:这道题是求覆盖目标子串所需要的子串数量,我们首先使用一个hashmap对目标子串所需要的字符以及每个字符所需要的数量进行遍历,定义LR两个指针,由于这个题目仍然是求最小子串,当我们遍历的字符串不满足要求时R指针不断向右遍历,并对窗口内的元素使用另一个hashmap进行存储,当我们遍历过的指针能够满足目标串所需相关字符的数量,这时我们再使L指针不断向右缩减窗口内元素的数量,不断循环这个过程,直到R走到字符串的最后一个元素

示例代码

我们给出示例代码:

class Solution {
    public String minWindow(String s, String t) {
        //创建双指针
        int left=0;
        int right=0;
        //定义两个hashmap
        HashMap<Character,Integer>map1=new HashMap<>();
        HashMap<Character,Integer>map2=new HashMap<>();
        int start=0;
        int len=Integer.MAX_VALUE;
        //设置要求
        int need=0;
        //设置满足情况
        int satisfy=0;
        //遍历要求
        for(char c: t.toCharArray()){
            map1.put(c,map1.getOrDefault(c,0)+1);
            if(map1.get(c)==1){
                need++;
            }
        }
        //进行遍历
        int n=s.length();
        while(right<n){
            map2.put(s.charAt(right),map2.getOrDefault(s.charAt(right),0)+1);
            if(map2.get(s.charAt(right)).equals(map1.get(s.charAt(right)))){
                satisfy++;
            }
            //优化结果
            while(satisfy==need){
                if(len>right-left+1){
                    len=right-left+1;
                    start=left;
                }
                char rm=s.charAt(left);
                if(map1.containsKey(rm)){
                    if(map1.get(rm).equals(map2.get(rm)))
                    satisfy--;
                }
                map2.put(rm,map2.get(rm)-1);
                left++;
            }
            right++;
        }
        if(len==Integer.MAX_VALUE){
            return "";
        }
        return s.substring(start,start+len);
    }
}

3.3 字符串的排列

题目描述

 

解题思路

这道题与上面的那道题目类似,同样是需要两个hashmap,一个是用来存储标准的字符以及其每个字符对应的元素的个数,按照上题的思路同理进行遍历,最后有一点不同的是我们最后将得到的最小值进行与符合要求的长度进行比对,相等返回TRUE ,不相等返回FALSE

示例代码

class Solution {
    public boolean checkInclusion(String s1, String s2) {
        //创建双指针
        int left=0;
        int right=0;
        //创建hashmap
        int[]nums1=new int[26];
        int[]nums2=new int[26];
        int maxLength=Integer.MAX_VALUE;
        int ask=0;
        int satisfy=0;
        //遍历要求
        for(int i=0;i<s1.length();++i){
            nums1[s1.charAt(i)-'a']++;
            if(nums1[s1.charAt(i)-'a']==1){
                ask++;
            }
        }
        //进行遍历
        while(right<s2.length()){
            nums2[s2.charAt(right)-'a']++;
            if(nums2[s2.charAt(right)-'a']==nums1[s2.charAt(right)-'a']){
                satisfy++;
            }
            while(satisfy==ask){
                if(right-left+1<maxLength){
                    maxLength=right-left+1;
                }
                if(nums2[s2.charAt(left)-'a']==(nums1[s2.charAt(left)-'a'])){
                    satisfy--;
                }
                nums2[s2.charAt(left)-'a']--;
                left++;
            }
            right++;
        }
        return maxLength==s1.length()?true:false;
    }
}

3.4 找到字符串中所有字母异位词

题目描述

 

解题思路

同样是与上题类似的解法,唯一的区别是在上题的解题基础上我们对每次遍历的minLength进行统计,如果符合我们条件的需求我们就直接将这个集合加入list即可

示例代码

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        //创建list
        List<Integer>list=new ArrayList<>();
        //基本类似的解题思路:
        //创建双指针
        int left=0;
        int right=0;
        //创建两个哈希表
         int[]nums1=new int[26];
        int[]nums2=new int[26];
        int ask=0;
        int satisfy=0;
        //遍历要求
        for(int i=0;i<p.length();++i){
            nums1[p.charAt(i)-'a']++;
            if(nums1[p.charAt(i)-'a']==1){
                ask++;
            }
        }
        //遍历实际的字符串
        while(right<s.length()){
            nums2[s.charAt(right)-'a']++;
            if(nums1[s.charAt(right)-'a']==nums2[s.charAt(right)-'a']){
                satisfy++;
            }
            //优化结果
            while(satisfy==ask){
                if(right-left+1==p.length()){
                    list.add(left);
                }
                if(nums2[s.charAt(left)-'a']==(nums1[s.charAt(left)-'a'])){
                    satisfy--;
                }
                nums2[s.charAt(left)-'a']--;
                left++;
            }
            right++;
        }
        return list;
    }
}

3.5 无重复字符的最长子串

题目描述

解题思路

这个题与前面的题目就有相对较大的区别了,从滑动窗口的种类来看,这个求的是最大的滑动窗口的大小,我们具体描述一下这道题的解题流程:创建hash表来存储我们每次进行遍历的元素,创建双指针进行遍历,R指针不断进行向右遍历每遍历一个元素我们就将元素加入到hash表中,当窗口中的元素数量不满足题目要求时(某个元素出现了两次),这时我们就将L指针不断向右移,直到满足题目中的要求,最后将我们最大的maxLength进行返回即可。

示例代码

class Solution {
    public int lengthOfLongestSubstring(String s) {
        
        //创建哈希表
        HashMap<Character,Integer>map=new HashMap<>();
        //定义双指针
        int left=0;
        int right=0;
        //定义总长度
        int n=s.length();
        int maxLength=0;
        while(right<n){
            map.put(s.charAt(right),map.getOrDefault(s.charAt(right),0)+1);
            while(map.get(s.charAt(right))>1){
                 map.put(s.charAt(left),map.get(s.charAt(left))-1);
                 left++;
            }
            if(right-left+1>maxLength){
                maxLength=right-left+1;
            }
            right++;
        }
       return maxLength; 
    }
}

3.6 考试的最大困扰度

题目描述

 

解题思路

这个题也是求最小的窗口,我们的解题思路也相对明确:就是用给定的k个万能值来填补两部分TRUE或者FALSE之间的空缺,R指针不断向右移,如果k无法满足空缺的话,L向右移动,直到K能够满足,一直遍历直到R指针遍历到字符串的最后

示例代码

class Solution {
    public int maxConsecutiveAnswers(String answerKey, int k) {
        //核心思路:使用提供的k的个万能值,来填补TRUE和FALSE之间的空缺值
        //创建两个指针
        int left=0;
        int right=0;
        //创建计数器
        int countT=0;
        int countF=0;
        int n=answerKey.length();
        int maxLength=0;
        //进行遍历循环
        while(right<n){
            char c=answerKey.charAt(right);
            
            if(c=='T'){
                countT++;
            }else{
                countF++;
            }
            //不符合的情况
            while(countT>k&&countF>k){
                char d=answerKey.charAt(left);
                //进行遍历
                if(d=='T'){
                    countT--;
                }else{
                    countF--;
                }
                left++;
            }
            if(right-left+1>maxLength){
                maxLength=right-left+1;
            }
            right++;
        }
        return maxLength;

    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/538535.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JAVA 可用的高性能docker镜像及如何使用?

目前docker hub上下载量很大的java、openjdk镜像都已经被弃用,不再维护,目前可用的java docker镜像有哪一些呢?哪一些镜像是主流的? 本文带有领略java可用的镜像资源、如何使用它们,如何构建springboot镜像? 1. 可用的java镜像 1.1. amazoncorretto 1.1.1. 什么是Corr…

环路详解:交换机环路产生的过程和原因图解

前言&#xff1a; 在了解环路之前得先了解交换机的工作原理&#xff0c;当然交换机的基本工作原理其实非常简单&#xff0c;只有“单播转发与泛洪转发”、“交换机MAC地址表”这两个&#xff01;其他的如vlan&#xff0c;生成树等也是在此基础上增加的&#xff0c;弥补交换机基…

node笔记_koa框架的路由

文章目录 ⭐前言⭐koa 原生路由写法⭐引入 koa-router&#x1f496; 安装koa-router&#x1f496; 动态读取路径文件作为路由 ⭐结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本文介绍koa框架的路由。 往期文章 node_windows环境变量配置 node_npm发布包 linux_配置no…

[网络安全]DVWA之XSS(Reflected)攻击姿势及解题详析合集

[网络安全]DVWA之XSS&#xff08;Reflected&#xff09;攻击姿势及解题详析合集 XSS(Reflected)-low level源代码姿势 XSS(Reflected)-medium level源代码姿势1.双写绕过2.大小写绕过 XSS(Reflected)-high level源代码str_replace函数 姿势 XSS(Reflected)-Impossible level源代…

ssh正反隧道(代理msf对icmp穿透监听)

ssh正向隧道&#xff1a; 就是将本地端口映射到远程上&#xff0c;相当访问本地端口就是访问远程的端口 正向 访问本地对应的是远程的端口 ssh -fNCL 本地ip:本地port:远程ip:远程port 用户远程ip/域名 实例&#xff1a; ssh -fNCL 192.168.222.128:90:192…

HTML的表单

前后端交互过程&#xff1a; 表单在 Web 网页中用来给访问者填写信息采集客户端信息&#xff0c;使网页具有交互的功能&#xff0c;用户填写完提交后&#xff0c;表单的内容就从客户端的浏览器传送到服务器上&#xff0c;经过服务器上程序处理后&#xff0c;再将用户所需信息传…

人机大战?——带你玩转三子棋(C语言)

TOC 1、前言 在学习完数组之后&#xff0c;我们就可以自己来实现一个简单游戏—三子棋了&#xff01; 为了确保程序的独立性&#xff1a;我们创建了一个源函数game.c 和test.c&#xff0c;一个头文件game.h test.c——测试游戏 game.c——游戏函数的实现 game.h——游戏函数…

Redis缓存数据库(三)

目录 一、概述 1、Redis架构 2、AKF 3、CAP原则 一、概述 1、Redis架构 Redis 有哪些架构模式&#xff1f;讲讲各自的特点 单机版 特点&#xff1a;简单 问题&#xff1a; 1、内存容量有限 2、处理能力有限 3、无法高可用。 主从复制 Redis 的复制&#xff08;replic…

python绘制散点图|散点大小和颜色深浅由数值决定

python绘图系列文章目录 往期python绘图合集: python绘制简单的折线图 python读取excel中数据并绘制多子图多组图在一张画布上 python绘制带误差棒的柱状图 python绘制多子图并单独显示 python读取excel数据并绘制多y轴图像 python绘制柱状图并美化|不同颜色填充柱子 python随机…

【嵌入式系统应用开发】FPGA——HLS入门实践之led灯闪烁

目录 1 HLS1.1 HLS简介1.2 HLS与VHDL/Verilog1.3 HLS优点与局限 2 环境配置3 HLS实例——Led点亮3.1 工程创建3.2 添加文件3.3 C仿真与C综合3.4 创建Vivado工程3.5 导入HLS生成的IP核3.6 添加实验代码3.7 编译生成获取结果 总结 1 HLS 1.1 HLS简介 HLS(High Level Synthesis)…

十大排序算法(上)直接插入排序、希尔排序、直接选择排序、堆排序

&#x1f308;目录 1. 排序的概念2. 常见的排序算法3. 排序算法的实现3.1 插入排序3.1.1 直接插入排序3.1.2 希尔排序&#xff08;缩小增量排序&#xff09; 3.2 选择排序3.2.1 基本思想3.2.2 直接选择排序3.2.3 堆排序 1. 排序的概念 排序&#xff0c;就是使一串记录&#xf…

阿里通义千问_VS_讯飞星火

今天终于获得阿里通义千问大模型体验授权&#xff0c;第一时间来测试一下效果&#xff0c;使用申请手机号登录&#xff08;地址&#xff1a;https://tongyi.aliyun.com&#xff09;后&#xff0c;需要同意通义千问大模型体验规则&#xff0c;如下图所示&#xff1a; 同意之后就…

【C++初阶】类与对象(中)之运算符重载 + 赋值运算符重载

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…

CPU性能优化:Cache

CPU性能提升&#xff1a;Cache机制 随着半导体工艺和芯片设计技术的发展&#xff0c;CPU的工作频率也越来越高&#xff0c;和CPU进行频繁的数据交换的内存的运行速度却没有相应的提升&#xff0c;于是两者之间产生了带宽问题。进而影响计算机系统的整体性能。CPU执行一条指令需…

C++/PTA 至多删三个字符

至多删三个字符 题目要求解题思路代码总结 题目要求 给定一个全部由小写英文字母组成的字符串&#xff0c;允许你至多删掉其中 3 个字符&#xff0c;结果可能有多少种不同的字符串&#xff1f; 输入格式&#xff1a; 输入在一行中给出全部由小写英文字母组成的、长度在区间 […

关于摆摊气球的调研-网红气球

本章主要介绍一下最近网红气球&#xff1a; 最近看到很多摆摊的抖音视频&#xff0c;都在说卖气球很好&#xff0c;成本低&#xff0c;收益高&#xff0c;所以调研了一下&#xff0c;网红气球分好几种&#xff1a; a,飘空气球&#xff1b; b.手持网红气球 c.青蛙 首先介绍飘空…

文件上传,内容逻辑数组绕过(22)

uploadd 第十三关 这一关告诉我们的&#xff0c;有一些上传漏洞需要配合这个文件包含和加解密。 这个先在一个图片源码里面写入php后门的脚本代码 这里也可以手工注入到图片的源码里面来&#xff0c;手工注入&#xff0c;如果采用16进制打开这个图片&#xff0c;这个图片在…

okhttp篇4:RetryAndFollowUpInterceptor

在上一篇 okhttp篇3&#xff1a;RealCall_yolan6824的博客-CSDN博客 中讲到RealCall无论是在execute还是enqueue方法中&#xff0c;都是通过getResponseWithInterceptorChain方法获取Request对应的Response的。而getResponseWithInterceptorChain这个方法&#xff0c;又是通过…

基于PyQt5的图形化界面开发——Windows内存资源监视助手[附带编译exe教程]

基于PyQt5的图形化界面开发——Windows内存资源监视助手[附带编译exe教程] 0. 前言1. 资源信息获取函数——monitor.py2. UI界面——listen.py3. main.py4. 运行效果5. 编译 exe 程序6. 其他PyQt文章 0. 前言 利用 PyQt5 开发一个 windows 的资源监视助手&#xff0c;在使用虚…

【vimsolo】让vim看起来像VSCode:颜色主题和状态栏的配置

文章目录 1. 目的2. 理念&#xff1a; vimsolo3. vimrc: 配置颜色4. vimrc: 配置状态栏5. 拷贝颜色主题和.vimrc: python安装脚本 1. 目的 习惯了 VSCode 默认的配色&#xff1a;黑色主题&#xff0c;蓝色状态栏。偶尔使用 Vim 时想让 vim 伪装的像 VSCode&#xff0c;不考虑花…