【算法】滑动窗口

news2024/9/24 21:17:31

目录

  • 1.概述
  • 2.算法框架
  • 3.应用

本文参考:
LABULADONG 的算法网站

1.概述

(1)滑动窗口可以用以解决数组/字符串的子元素相关问题,并且可以将嵌套的循环问题,转换为单循环问题,从而降低时间复杂度。故滑动窗口算法的复杂度一般为 O(n)。

(2)滑动窗口的基本思想如下:

  • 首先使用双指针维护一个子数组,别称为 left 和 right。left 指向窗口的左端点,right 指向窗口的右端点。如下图所示:
    在这里插入图片描述
  • 窗口随着 right 指针向右滑动开始遍历整个数组区间(即增大窗口);

在这里插入图片描述

  • 而在每次迭代内部(即针对每一次 right)要对子数组区间是否满足要求进行判断。如果子数组区间不能够满足条件则将 left 指针向右移动(即缩小窗口),这样窗口就实现了向右滑动。
    在这里插入图片描述

2.算法框架

滑动窗口的算法框架如下:

class Solution {
    /**
     * @param1: 待处理的序列,一般为数组或字符串
     * @description: 滑动窗口算法框架
     */
    public void slidingWindow(int[] nums) {
        //此处使用 HashMap 来表示滑动窗口,也可根据具体情况使用其它存储结构
        Map<Character, Integer> window = new HashMap<>();
        int length = nums.length;
        //定义滑动窗口的左右端点,初始值均为 0
        int left = 0;
        int right = 0;
        while (right < length) {
            //即将移入窗口的元素
            int inEle = nums[right];
            //操作 right,增大窗口
            right++;
            //更新窗口内的数据
            //...
            
            //判断窗口是否要缩小
            while (window needs shrink) {
                //即将移出窗口的元素
                int outEle = nums[left];
                //操作 left,缩小窗口
                left++;
                //更新窗口内的数据
                //...
            }
        }
    }
}

3.应用

(1)下面以 LeetCode 中的76.最小覆盖子串这题为例,来使用上述的滑动窗口框架:

在这里插入图片描述

  • 如果直接使用暴力穷举法,其思路为使用两层 for 循环来枚举 s 的所有子串,并且逐一判断每个子串是否包含字符串 t 中的所有字母,如果包含则更新答案。显然该方法的时间复杂度肯定超过 O(n2),其代码结构大致如下所示:
for (int i = 0; i < s.length(); i++) {
    for (int j = i + 1; j < s.length(); j++) {
        // isIncluded(s, i, j) 用于判断子串 s[i...j] 是否包含字符串 t 中的所有字母
        if (isIncluded(s, i, j, t)) {
            //更新答案
        }
    }
}
  • 使用滑动窗口算法的具体代码实现如下:
class Solution {
    public String minWindow(String s, String t) {
        int sLen = s.length();
        // window 中记录滑动窗口内的字符以及对应出现的次数
        HashMap<Character, Integer> window = new HashMap<Character, Integer>();
        // need 记录字符串 t 中的字符以及对应出现的次数
        HashMap<Character, Integer> need = new HashMap<Character, Integer>();
        //将字符串 t 中的字符存入哈希表 need 中,key/value 为字符/对应出现的次数
        for (int i = 0; i < t.length(); i++) {
            char c = t.charAt(i);
            need.put(c, need.getOrDefault(c, 0) + 1);
        }
        //定义滑动窗口的左右端点,初始值均为 0
        int left = 0;
        int right = 0;
        //valid 记录窗口中 t 中不重复字符的个数
        int valid = 0;
        //记录最小覆盖子串的起始索引以及长度
        int start = 0, minLen = Integer.MAX_VALUE;
        while (right < sLen) {
            char c = s.charAt(right);
            right++;
            //更新窗口内的数据,如果字符 c 存在于 t 中,则将其加入到 window 中
            if (need.containsKey(c)) {
                window.put(c, window.getOrDefault(c, 0) + 1);
                /*
                    如果t中所有的字符c都已经加入到窗口中
                    注意:使用"=="比较 Integer 类型的值时,值的范围只能在 -128 ~ 127 之间,否则会出错
                    详情请见https://www.cnblogs.com/mrhgw/p/10449391.html
                */
                if (window.get(c).equals(need.get(c))) {
                    valid++;
                }
            }
            //判断左侧窗口是否要收缩,t 中的所有字符都已经加入到窗口中
            while (valid == need.size()) {
                //更新最小覆盖子串
                if (right - left < minLen) {
                    start = left;
                    minLen = right - left;
                }
                //d 是即将移出窗口的字符
                char d = s.charAt(left);
                left++;
                //更新窗口内的数据
                if (need.containsKey(d)) {
                    if (window.get(d).equals(need.get(d))) {
                        valid--;
                    }
                    window.put(d, window.get(d) - 1);
                }
            }
        }
        return (minLen == Integer.MAX_VALUE) ? "" : s.substring(start, start + minLen);
    }
}

(2)大家可以去 LeetCode 上找相关的滑动窗口的题目来练习,或者也可以直接查看LeetCode算法刷题目录 (Java)这篇文章中的滑动窗口章节。如果大家发现文章中的错误之处,可在评论区中指出。

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

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

相关文章

【数据分析】(task5)数据建模及模型评估

note 文章目录note一、建立模型二、模型评估2.1 交叉验证2.2 混淆矩阵/recall/accuracy/F12.3 ROC曲线三、Pyspark进行基础模型预测时间安排Reference一、建立模型 下载sklearn的命令pip install scikit-learn。 from sklearn.model_selection import train_test_split impor…

ARP渗透与攻防(二)之断网攻击

ARP断网攻击 系列文章 ARP渗透与攻防(一)之ARP原理 1.环境准备 kali 作为ARP攻击机&#xff0c;IP地址&#xff1a;192.168.110.26 MAC地址&#xff1a;00:0c:29:fc:66:46 win10 作为被攻击方&#xff0c;IP地址&#xff1a;192.168.110.12 MAC地址&#xff1a;1c:69:7a:a…

Tkinter的Entry与Text

Tkinter界面设计之输入控件Entry以及文本框控件Text。 目录 一、放置控件 1. pack()函数 2. place()函数 3. grid()函数 二、简单控件 1. Entry输入控件 1.1 tk.StringVar()函数&#xff1a;接收一个字符串 1.2 tk.Entry()函数&#xff1a;设置一个输入控件E 2. Text文…

CMake多文件编译

之前学习ceres-solver中的3d相关的源码的时候&#xff0c;发现对于CMake多文件工程编译中对于CMakeLists.txt的编写和处理的理解运用还是比较模糊&#xff0c;这里整理梳理一下对于不同文件夹数量如何使用。 参考文章&#xff1a; CMake使用详解二&#xff08;多文件编译&…

maya常用操作

1&#xff1a;重置工作区。2&#xff1a;切换视图。按空格切换视图。3&#xff1a;未选中状态&#xff0c;按shift&#xff0c;再点右键&#xff0c;可以打开交互式创建。这样可以在栅格上创建想要的大小。不选中交互式创建的话&#xff0c;创建的是默认未知。默认未知为正中间…

linux系统中利用QT实现车牌识别的方法

大家好&#xff0c;今天主要和大家分享一下&#xff0c;如何利用QT实现车牌识别的方法。 目录 第一&#xff1a;车牌识别基本简介 第二&#xff1a;车牌识别产品申请 第三&#xff1a;百度车牌识别API接口 第四&#xff1a;车牌识别综合测试 第一&#xff1a;车牌识别基本简…

Scala快速入门

Scala简介 Scala是一门现代的多范式编程语言&#xff0c;平滑地集成了面向对象和函数式语言的特性。Scala运行于Java平台&#xff08;JVM&#xff0c;Java 虚拟机&#xff09;上&#xff0c;并兼容现有的Java程序&#xff0c;Scala代码可以调用Java方法&#xff0c;访问Java字…

ArcGIS Pro脚本工具(17)——生成多分式标注

​朋友们&#xff0c;你们知道ArcGIS里面分式标注的四种写法么&#xff1f; 放错图了&#xff0c;是这个 分式标注的四种形式我们可以把这类叫分式标注&#xff0c;网上也有博主分享过如何在ArcGIS中制作这类标注&#xff0c;但我觉得仍有一些不足。 一是基本都使用VB编写&…

中文问题相似度挑战赛

赛题概要 请本赛题排行榜前10位的队伍&#xff0c;通过作品说明提交源代码&#xff0c;模型以及说明文档&#xff0c;若文件过大&#xff0c;可发送至官网邮箱AICompetitioniflytek.com, 若截止时间内为提交&#xff0c;官方会通过电话联系相关选手&#xff0c;若未接到通知或…

WPF作图神器Interactive DataDisplay的初步使用

文章目录安装初步使用安装 Interactive DataDisplay是一款比较优秀的C#绘图控件&#xff0c;尽管与一些商业控件还有不小的差距&#xff0c;关键是开源免费轻量。 在VS中安装控件十分简单&#xff0c;本测试基于Net Core5.0&#xff0c;在VS的菜单栏->工具->NuGet包管理…

HomeLab 常用工具一:filebrowser

前言在实际使用过程中&#xff0c;我们通常都有基于WEB 的文件操作需求&#xff08;例如从一台陌生设备上想打开看一下&#xff0c;图片等&#xff09;&#xff0c;和nextcloud 相比 filebrowser 更为轻巧也更为方便。一、filebrowser 安装这里基于docker 安装和使用&#xff0…

Prometheus 动态拉取监控服务

Prometheus 版本 2.41.0 平台统一监控的介绍和调研直观感受PromQL及其数据类型PromQL之选择器和运算符PromQL之函数Prometheus 配置身份认证Prometheus 动态拉取监控服务 我们在以前的实例中配置Prometheus 的target 都是手动配置&#xff0c;这在监控目标少的情况下还可以接受…

【基础】BMP格式

BMP格式位图 (BMP)简介格式1.1图和调色板的概念1.2 bmp文件格式1.2.1 位图文件头 14字节1.2.2 位图信息头 40字节1.2.3 调色板1.2.4 注意位图 (BMP)简介 BMP取自位图Bitmap的缩写&#xff0c;也称为DIB&#xff08;与设备无关的位图&#xff09;&#xff0c;是一种独立于显示器…

【苹果家庭群发推】软件keychain中刚打开的证书下载的证书文件要决不会报错 UNTimeIntervalNotificationTrigge

推荐内容IMESSGAE相关 作者✈️IMEAX推荐内容iMessage苹果推软件 *** 点击即可查看作者要求内容信息作者✈️IMEAX推荐内容1.家庭推内容 *** 点击即可查看作者要求内容信息作者✈️IMEAX推荐内容2.相册推 *** 点击即可查看作者要求内容信息作者✈️IMEAX推荐内容3.日历推 *** …

linux入门---linux基本指令

目录标题云服务器选择云服务器购买xshell下载如何登陆云服务器Linux的新建与删除新建删除云服务器选择 学习linux的时候云服务器是一个非常重要的工具&#xff0c;那么我们在购买云服务器的时候有很多选择比如说&#xff1a;华为云&#xff0c;腾讯云&#xff0c;阿里云等等&a…

活动星投票网络文明公益广告网络评选微信的投票方式线上免费投票

“网络文明公益广告”网络评选投票_不记名投票小程序_投票帮手免费畅享_扫码投票微信小程序手机互联网给所有人都带来不同程度的便利&#xff0c;而微信已经成为国民的系统级别的应用。现在很多人都会在微信群或朋友圈里转发投票&#xff0c;对于运营及推广来说找一个合适的投票…

ROS2机器人编程简述humble-第三章-PERCEPTION AND ACTUATION MODELS .1

书中&#xff0c;第三章主题&#xff1a;First Behavior: Avoiding Obstacles with Finite States Machines本节旨在应用到现在为止所展示的一切来创建看似“聪明”的行为。这个练习将介绍的许多东西结合起来&#xff0c;并展示使用ROS2编程机器人的效率。此外&#xff0c;将解…

第五届字节跳动青训营 前端进阶学习笔记(八)React框架入门

文章目录前言React 的设计思路1.传统JavaScript更新UI的痛点2.我们对UI代码的需求3.组件&#xff08;1&#xff09;组件定义&#xff08;2&#xff09;组件设计&#xff08;3&#xff09;组件结构4.React的生命周期React的基本语法1.JSXReact的实现1.虚拟DOM2.响应数据的实现前…

Java面试题,Spring Bean的注册与依赖注入

Spring Bean的注册与依赖注入一、XML文件中&#xff0c;将Bean创建到Spring容器1. 基本类型注册2. 类装配3. 有参构造方法装配4. 扩展注入5. Bean的作用域6. Bean的其他配置二、配置类中&#xff0c;将Bean创建到Spring容器1. 在mapper、service、controller中创建&#xff0c;…

计网必会:HTPP详解(非常全面)、cookie、缓存

文章目录应用层协议Web和HTTPHTTP 概述采用非持续连接的HTTPRTT 往返时间的定义**三次握手过程**采用持续连接的HTTPHTTP到底采用哪个&#xff1f;HTTP 的报文格式请求报文功效格式响应报文状态码格式Cookie什么是cookieWeb缓存在学习的过程很多人都遇到了HTTP和Cookie&#xf…