首页 > 编程语言 >滑动窗口-java

滑动窗口-java

时间:2024-05-28 09:32:37浏览次数:25  
标签:head 下标 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 

总结

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

标签:head,下标,java,队列,元素,滑动,窗口
From: https://blog.csdn.net/m0_63267251/article/details/138684133

相关文章

  • JAVA------基础篇
    java基础1.JDKJDK:javadevelopmentkitJRE:javaruntimeenvironmentJDK包含JREjava跨平台:因为java程序运行依赖虚拟机,虚拟机需要有对应操作系统的版本,而jre中有虚拟机。当你想要在Linux系统下运行,则需要安装对应的虚拟机,及对应的jdk版本,而对应的jdk版本中的jre有对......
  • TCP滑动窗口
    发送方发送报文不再使用一个一个报文发送然后等待一个一个确认,而是进行一段(多个报文)发送接收方接收到数据后,发送当前接收到数据序列值+1,以及下一次可以接收的窗口值 也就是说,发送方需要配合接收方接受的窗口大小来确定数值发送 发送方窗口左边为后沿,右边为前沿。1.当......
  • 基于Java的高校学生勤工助学优派系统的设计与实现(论文+源码)_kaic
    摘  要高校勤工助学管理系统的出现,让学生的工作更加标准,不仅仅使高校办公室的办公水平以及管理水平大大提高,还优化了勤工助学资金的使用方式方法,完善了资助所需费用的资源配置,可以卓有成效地缩减学校的管理经费。本系统主要采取Java语言以及面向对象的开发模式,进行编码和......
  • 基于JAVA的高校学生请假管理系统的设计与实现(论文+源码)_kaic
    摘要随着我国越来越重视教育事业的发展,学生数量在大大增加,将用基于网络的学生‎‏管理系统融入高校管理日常事务处理中,达到改善教学管理效率的目的。本系统以Java语言进行编写设计,前端使用Vue,采用Springboot框架,利用Idea开发工具,运用MySQL数据库进行数据存储,主要流程为学......
  • 一步一步实现WPF透明化窗口
    这一篇教程讲述如何实现透明窗体和透明控件,在WindowStyle设置为none情况下拖拽窗口,半透明作为较容易实现的一种美观化,对于大多数美工较弱的开发者来说实用性不错,能在一些平面化设计场合发挥简单而有效的美化效果。  实现效果1:窗体整体半透明   实现效果2:窗体全透明......
  • 你不知道的JavaScript(上中下合集) (作者 [美] Kyle Simpson 译者 赵望野 梁杰 单业 姜
    书:pan.baidu.com/s/199LHxxIlMixw3gYSY8tyPw?pwd=ywxg提取码:ywxg作用域与闭包:详细解释了词法作用域、动态作用域以及闭包的概念,展示了它们如何影响变量和函数的可访问性。函数作用域与块作用域:区分了函数作用域和块作用域,并解释了let和const等关键字如何引入块级作用域。变量......
  • JAVA IO流
    文件基础知识: 创建文件的三种方法:publicstaticvoidcreate01(){//根据路径创建一个file对象Stringpath="D:\\test01.txt";Filefile01=newFile(path);try{file01.createNewFile();System.out.println("......
  • 基于JAVA GUI的JDBC连接数据库
     要在JavaGUI中连接数据库,需要执行以下几个步骤:导入必要的包。你需要导入Java数据库连接相关的包,例如java.sql和javax.sql。与数据库连接相关的类和接口。  (1)DriverManger类。DriverManager类用于加载JDBD驱动并且创建其与数据库的连接。在DriverManager类中定义了......
  • java Smart系统-题库及试卷管理模块的设计与开发
    摘 要SMART系统是一个采用新思路、新架构、新技术开发出来的一个新型智能在线考试信息管理系统,该系统主要实现了学生在线考试与评估以及对各种评估信息的管理和维护。本文针对教育工作的具体需求,用struts+spring+hibernate搭建的框架为设计平台,以B/S(Browser/Server)模式......
  • 第七十五节 Java设计模式 - 模板方法模式
    Java设计模式-模板方法模式在模板模式中,父抽象类公开几个抽象方法供子类实现。在父抽象类中有另一个方法或几个方法使用抽象方法来实现业务逻辑。抽象方法通常用于父类所需的每个步骤。例如,为了使用新的软件,我们需要下载,安装,配置和运行。如果我们要使用模板模式来编码逻......