滑动窗口-java

主要通过单调队列来解决滑动窗口问题,得到滑动窗口中元素的最大值和最小值。

目录

前言

一、滑动窗口

二、算法思路

1.滑动窗口

 2.算法思路

3.代码详解

三、代码如下

1.代码如下

2.读入数据

3.代码运行结果

总结


前言

主要通过单调队列来解决滑动窗口问题,得到滑动窗口中元素的最大值和最小值。


提示:以下是本篇文章正文内容,下面案例可供参考

一、滑动窗口

给定一个大小为 n≤1000000的数组。

有一个大小为 k 的滑动窗口,它从数组的最左边移动到最右边。

你只能在窗口中看到 k个数字。

每次滑动窗口向右移动一个位置。

以下是一个例子:

该数组为 [1 3 -1 -3 5 3 6 7],k 为 3。

窗口位置最小值最大值
[1 3 -1] -3 5 3 6 7-13
1 [3 -1 -3] 5 3 6 7-33
1 3 [-1 -3 5] 3 6 7-35
1 3 -1 [-3 5 3] 6 7-35
1 3 -1 -3 [5 3 6] 736
1 3 -1 -3 5 [3 6 7]37

你的任务是确定滑动窗口位于每个位置时,窗口中的最大值和最小值。

输入格式

输入包含两行。

第一行包含两个整数 n 和 k,分别代表数组长度和滑动窗口的长度。

第二行有 n 个整数,代表数组的具体数值。

同行数据之间用空格隔开。

输出格式

输出包含两个。

第一行输出,从左至右,每个位置滑动窗口中的最小值。

第二行输出,从左至右,每个位置滑动窗口中的最大值。

输入样例:

8 3
1 3 -1 -3 5 3 6 7

输出样例:

-1 -3 -3 -3 3 3
3 3 5 5 6 7

二、算法思路

1.滑动窗口

我们先解释一下滑动窗口,以上述测试样例,滑动窗口的大小为3。

图1.1滑动窗口 

当我们继续遍历元素的时候,为了保证窗口内一直是3个元素,每加入一个元素,就要剔除一个最左边元素,直到遍历到最后一个元素,这就是滑动窗口。

 2.算法思路

图2.1思路模拟 

我们先来求当前滑动窗口的最小值。我们以 图2.1中的滑动窗口为例,求此窗口的最小值从图中可以得到是-3,它前面的3和1是不可能被当作答案输出的;当有两个索引i < j(即i在j的左侧),且存在arr[i] >= arr[j],那么当滑动窗口向右移动,i还在滑动窗口内,那么j一定还在窗口内(由于i在j的左侧所保证的)。因此由于arr[j]的存在,那么arr[i]就一定不会被当作最小值答案输出,那么我们就可以将arr[i]永久移除。

那么我们可以用一个队列来存储还没有被移除的元素的下标,在队列中,这些元素下标按照从小到大的顺序被存储在队列当中,并且有一个特性,保持其中索引对应的元素是单调递增的那么我们当前滑动窗口中最小值的元素就是队列中队头元素对应的数组元素。

当滑动窗口右移时,我们需要把一个新元素放入队列当中。

为了保持队列中的下标对应的元素是单调递增的特性,我们需要将新元素与队尾元素进行比较,如果队尾元素对应的数组元素大于等于新加入的元素,那么我们就可以将队尾元素永久的剔除,将他弹出队列,重复的执行上述操作,直到队列为空或者队尾元素小于新加入的元素。

当然在窗口向右移动的过程中,我们还需要不断地从队列中弹出队头元素,来保证队列中的下标都是滑动窗口中的元素的下标。

3.代码详解

我们引入一位整型数组arr来存储元素,用一维整型数组queue来存储滑动窗口内元素的下标。引入一个整型变量k来表示滑动窗口的长度,用整型变量head表示队头指针,rear表示队尾指针。

通过一个for循环来遍历每个元素,同时我们要来判断此时是否需要弹出队头元素,队尾元素的下标就是此时遍历的元素i,那么队头元素的下标就为 i - k + 1,如果i - k + 1大于队头存储的元素(队列中存储的是元素的下标)即i - k + 1 > queue[head],此时就说明要弹出队头元素来保证队列中的元素个数为k个;然后我们又需要将新加入的元素来与队尾元素对应的数组元素进行比较,如果存在队尾元素对应的数组元素大于等于新加入的元素即arr[queue[rear]] >= arr[i],就说明队尾元素对应的数组元素不可能被当作滑动区间的最小值被输出,就可以将队尾元素弹出,直到队列为空或者队尾元素对应的数组元素小于新加入的元素。接下来将新加入的元素的下标进行入队操作。

最后当滑动窗口中有k个元素的才会输出答案,那么当要输出第一个答案的时候滑动窗口的元素对应的数组下标一定是k-1,后面每加入元素下标肯定是比k-1要大的,故只有下标大于k-1的时候才会输出一个答案,求最小值我们只需要输出一下队头元素对应的数组元素即可。

求滑动窗口的最大值我们只需要重复一下上述操作,将队列中的元素保证为单调递减即可,将新加入的元素与队尾元素对应的数组元素进行比较,如果新加入的元素大于等于队尾元素,那么就说明队尾元素对应的数组元素是小的值,不可能被当作滑动窗口的最大值进行输出,就弹出队尾元素。最后滑动窗口的最大值还是队列中的队头元素对应的数组元素。

三、代码如下

1.代码如下


import java.io.*;
import java.util.*;
public class 滑动窗口 {
    static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static int N = 1000010;
    static int[] arr = new int[N];
    //队列里面存的是下标
    static int[] queue = new int[N];

    public static void main(String[] args) {
        Scanner sc = new Scanner(br);
        int n = sc.nextInt();
        int k = sc.nextInt();
        int head = 0;
        int rear = -1;
        for(int i = 0;i < n;i++){
            arr[i] = sc.nextInt();
        }
        for(int i = 0;i < n;i++){
            //判断是否弹出队头元素,且每次就弹出一个元素,就写if就可以了
            if (head <= rear && i - k + 1 > queue[head]){
                head++;
            }
            //保证队列中元素的下标对应的元素是一个递增序列,队尾元素大于等于新加入的元素就弹出队尾元素
            while (head <= rear && arr[queue[rear]] >= arr[i]){
                rear--;
            }
            //新元素入队
            queue[++rear] = i;
            //因为这道题是当滑动窗口中有k个元素的话才会输出一个答案,那么第一个答案对应的元素的下标肯定是k-1,后续要输出的答案的元素的下标肯定比k-1大
            if(i >= k-1 ){
                pw.print(arr[queue[head]]+" ");
            }
        }
        pw.println();
        head = 0;
        rear = -1;
        for(int i = 0;i < n;i++){
            if (head <= rear && i - k + 1 > queue[head]){
                head++;
            }
            //保证队列中元素的下标对应的元素是一个递减序列,队尾元素对应的下标元素小于等于新加入的元素就弹出队尾元素
            while (head <= rear && arr[queue[rear]] <= arr[i]){
                rear--;
            }
            //新元素入队
            queue[++rear] = i;
            //因为这道题是当滑动窗口中有k个元素的话才会输出一个答案,那么第一个答案对应的元素的下标肯定是k-1,后续要输出的答案的元素的下标肯定比k-1大
            if(i >= k-1 ){
                pw.print(arr[queue[head]]+" ");
            }
        }
        pw.flush();
    }
}

2.读入数据

8 3
1 3 -1 -3 5 3 6 7

3.代码运行结果

-1 -3 -3 -3 3 3 
3 3 5 5 6 7 

总结

主要我们理解如何保持单调队列中元素的特性,知道如何维护队列即可,这是这道题的关键所在。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

文件上传漏洞:pikachu靶场中的文件上传漏洞通关

目录 1、文件上传漏洞介绍 2、pikachu-client check 3、pikachu-MIME type 4、pikachu-getimagesize 最近在学习文件上传漏洞&#xff0c;这里使用pikachu靶场来对文件上传漏洞进行一个复习练习 废话不多说&#xff0c;开整 1、文件上传漏洞介绍 pikachu靶场是这样介绍文…

Docker快速安装SQL Server 2022

说明&#xff1a; 系统&#xff1a;Ubuntu 24.04 LTS 拉取SQL Server Docker镜像 docker pull mcr.microsoft.com/mssql/server:2022-CU12-ubuntu-22.04创建数据目录 sudo mkdir /var/mssql_data sudo chmod 777 /var/mssql_data说明&#xff1a; 权限设置为777&#xff0…

[集群聊天服务器]----(十)Nginx的tcp负载均衡配置--附带截图

接着上文&#xff0c;我们剖析了服务端和客户端的代码&#xff0c;但是单台服务器的并发量是有限的&#xff0c;面对并发量的要求&#xff0c;我们就需要引入Nginx来实现并发量的要求&#xff0c;将用户请求分发到不同的服务器上分担压力&#xff0c;这就是负载均衡。 选择负…

最新php项目加密源码

压缩包里有多少个php就会被加密多少个PHP、php无需安装任何插件。源码全开源 如果上传的压缩包里有子文件夹&#xff08;子文件夹里的php文件也会被加密&#xff09;&#xff0c;加密后的压缩包需要先修复一下&#xff0c;步骤&#xff1a;打开压缩包 》 工具 》 修复压缩文件…

JavaSE——集合框架二(2/6)-综合案例-斗地主游戏(做牌、洗牌、发牌、排序、看牌)

目录 需求与分析 具体实现 牌类定义 房间类定义 初步测试 启动游戏 运行案例 需求与分析 需求 总共有54张牌点数&#xff1a;"3","4","5","6","7","8","9","10","J",&qu…

MyBatis的基础操作

目录 一.什么是MyBatis? 二.使用MyBatis的准备工作 1.引入依赖: 2.配置数据库连接字符串(建立MaBatis和MySQL的连接) 3.在model包中建立数据库对应的实体类UserInfo 三.通过注解的方式实现MyBatis的开发 1.插入语句(Insert) 2.删除语句(Delete) 3.更新语句(Update) 4…

驱动开发:内核MDL读写进程内存

100编程书屋_孔夫子旧书网 MDL内存读写是最常用的一种读写模式,通常需要附加到指定进程空间内然后调用内存拷贝得到对端内存中的数据,在调用结束后再将其空间释放掉,通过这种方式实现内存读写操作,此种模式的读写操作也是最推荐使用的相比于CR3切换来说,此方式更稳定并不会…

c语言--结构体

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 结构体概念简介 c语言数组是一些相同类型的数据的集合。 这个结构体就是一些可以是不同类型的集合。 比如描述班里的一个人&#xff0c;他可能需要名字(字符串),也需要年龄(整数)。 这种情况就需要用结构体。 …

【Django】中间件实现钩子函数预处理和后处理,局部装饰视图函数

在app文件夹里新建middleware.py继承MiddlewareMixin&#xff0c; 编写中间件类&#xff0c;重写process_request、process_response钩子函数 from django.http import HttpRequest, HttpResponse from django.utils.decorators import decorator_from_middleware from django…

使用 Django 与 Redis 实现缓存优化

文章目录 什么是Redis&#xff1f;为什么选择Django与Redis&#xff1f;如何在Django中使用Redis&#xff1f;总结与拓展 在Web开发中&#xff0c;性能优化是一个至关重要的方面。而使用缓存是提高Web应用性能的常见方法之一。在这篇文章中&#xff0c;我们将探讨如何结合Djang…

layui扩展件(xm-select)实现下拉框

layui扩展件&#xff08;xm-select&#xff09;实现下拉框 扩展组件 xm-select 效果图 html代码 <div class"layui-inline"><label class"layui-form-label">职位</label><div class"layui-input-inline" style"wid…

Linux 使用 yum安装 ELK服务,yum 安装elasticsearch和Kibana(未写完)

文章目录 环境准备ELK组件介绍安装Elasticsearch安装Kibana 丢弃下载ELK 服务安装包Elasticsearch安装 Tips:关闭elasticsearch https 环境准备 ELK组件介绍 ElasticSearch &#xff1a; 是一个近实时&#xff08;NRT&#xff09;的分布式搜索和分析引擎&#xff0c;它可以用…

Chrome谷歌浏览器如何打开不安全页面的禁止权限?

目录 一、背景二、如何打开不安全页面被禁止的权限&#xff1f;2.1 第一步&#xff0c;添加信任站点2.2 第二步&#xff0c;打开不安全页面的权限2.3 结果展示 一、背景 在开发过程中&#xff0c;由于测试环境没有配置 HTTPS 请求&#xff0c;所以谷歌浏览器的地址栏会有这样一…

K8S-pod资源 探针

一.pod资源限制&#xff1a; 对pod资源限制原因&#xff1a;高并发占用所有的cpu资源、内存资源、会造成雪崩 当定义 Pod 时可以选择性地为每个容器设定所需要的资源数量。 最常见的可设定资源是 CPU 和内存大小&#xff0c;以及其他类型的资源。 方式&#xff1a; 对pod做…

金锋关晓柔短视频:成都鼎茂宏升文化传媒公司

金锋关晓柔短视频&#xff1a;情感与创意的交织 在短视频的浪潮中&#xff0c;无数创作者凭借独特的视角和创意脱颖而出。其中&#xff0c;金锋和关晓柔共同打造的短视频系列以其深厚的情感内涵和精湛的创意表达&#xff0c;成都鼎茂宏升文化传媒公司吸引了大量观众的关注&…

leetcode 1241每个帖子的评论数(postgresql)

需求 编写 SQL 语句以查找每个帖子的评论数。 结果表应包含帖子的 post_id 和对应的评论数 number_of_comments 并且按 post_id 升序排列。 Submissions 可能包含重复的评论。您应该计算每个帖子的唯一评论数。 Submissions 可能包含重复的帖子。您应该将它们视为一个帖子。…

C语言常用字符串处理函数

C语言中包含了很多对字符串处理的函数,要使用这些函数&#xff0c; 首先需要导入头文件#include <string.h> 1. strlen() -- 计算字符串长度 原型: size_t strlen(char const *string); 例: char *str "abcde"; size_t len strlen(str); // 结果为…

应用程序中的会话管理和Cookie安全指南

应用程序中的会话管理和Cookie安全指南 在现代应用程序中&#xff0c;会话管理和Cookie安全是确保用户信息和数据安全的重要组成部分。本文将详细介绍会话管理的最佳实践以及如何通过安全的Cookie设置来保护会话ID的交换。 单点登录&#xff08;SSO&#xff09;及会话管理机制…

Ubuntu24.04安装tabby-terminal-1.0.207并处理依赖

1 下载 tabby-terminal-1.0.207 地址&#xff1a; https://github.com/Eugeny/tabby/releases 点击show all 36 assets 选择 tabby-1.0.207-linux-x64.deb 并下载。 2 依赖下载 gconf2_3.2.6-3ubuntu6_amd64.deb gconf2-common_3.2.6-3ubuntu6_all.deb gconf-service_3.2.6-…

【软件设计师】网络安全

1.网络安全基础信息 网络安全的五个基本要素&#xff1a; 机密性&#xff1a;确保信息不暴露给未授权的实体或进程 完整性&#xff1a;只有得到允许的人才能修改数据&#xff0c;并且能判断出数据是否已被修改 可用性&#xff1a;得到授权的实体在需要时可以访问数据&#xff0…