首页 > 编程语言 >LeetCode100之滑动窗口最大值(239)--Java

LeetCode100之滑动窗口最大值(239)--Java

时间:2024-11-02 13:46:37浏览次数:6  
标签:Java nums -- 元素 queue 队列 LeetCode100 滑动 窗口

1.问题描述

        给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回 滑动窗口中的最大值 

        示例1

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7

        示例2 

输入:nums = [1], k = 1
输出:[1]

        提示

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104
  • 1 <= k <= nums.length

        难度等级

                困难

        题目链接

           滑动窗口的最大值

2.解题思路

        这道题要我们求滑动窗口的最大值,也就是窗口内最大的那个数,一开始我的想法是确定窗口之后,再用一个for循环来遍历,找出里面的最大值,我一开始就是这么做的,可以通过,但是耗时很长,和我接下来要提供的这种方法,在时间上相差了10倍左右。

        这道题我们可以采用双端队列来进行解题。我们都知道,队列有先进先出的特点,而滑动窗口在移动的过程中,也是先进先出,很符合队列的特点,那为什么是采用双端队列呢?因为我们要找到的是滑动窗口的最大值,所以我们要保证队列中的元素是递减的,这样队头的元素就是我们要的最大值,为了保证队头的元素是递减的,我们从队尾放入元素的时候,就必需能够把队尾的元素取出来,而双堆队列正好符合了我们的需求,它可以从队头取元素,也可以从队尾取元素。

            //双端队列
            Deque<Integer> queue = new LinkedList<>();

        解决了为什么时候双端队列之后,我们就可以开始初始化存储答案的数组和双端队列了,将题目所给数组的第一个索引存入队列中,便于后续的遍历。同时定义一个指针p,用来向存储答案的数组存入元素。

        //存储答案
        int[] data = new int[nums.length - k + 1];
        //初始化队列
        queue.offer(0);
        int p =0;

        接着,我们就可以开始遍历了。首先,我们需要先将队列中已经不在滑动窗口内的元素索引移除(i - k + 1)是滑动窗口最左边的索引,若队头索引比(i-k+1)小的话,那已经不在滑动窗口内部了,将队友索引移除,在移除之前,我们得先加一个判断队列是否为空的操作,避免出现越界的情况。(这一部分的操作相当于是改变滑动窗口的左边界。)

            //移除不在窗口内的元素(队列头)
            while(!queue.isEmpty() && queue.peekFirst() < i -k +1){
                queue.pollFirst();
            }

        然后,我们就可以来改变滑动窗口的右边界了。前面我们提到,我们要确保队列里的元素是递减的,其实指的是队列里的索引指向的数组中的元素是要递减的。所以我们在往队列中添加元素之前,需要想把队列尾中小于我们要添加的索引对应的元素移除,才能保证递减的要求。用一个循环不断的比较移除,直到遇到比自己大的元素之后,我们就可以把当前索引存入队列当中了。(这一部分操作相当于是改变滑动窗口的右边界。)

            //保持窗口内的元素递减(队列尾),确保队列中的元素是递减的
            while(!queue.isEmpty() && nums[queue.peekLast()] < nums[i]){
                queue.pollLast();
            }
            //添加元素索引
            queue.offer(i);

        左右边界都改变之后,就实现了滑动。最后,我们只需要将队列头的索引对应的数组元素存放到答案数组中即可。注意:当滑动窗口的大小到达为k之前(i >= k-1),是不存在什么窗口内的最大值的,所以如果窗口还没到达最大时,不用进行添加最大值的操作。

            //窗口的大小满足k后才能寻找最大值
            if(i >= k -1){
                data[p++] = nums[queue.peekFirst()];
            }

        重复上述操作,知道整个数组遍历完成之后,我们就找到了各个窗口中的最大值了,直接返回即可。

3.代码展示

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        //存储答案
        int[] data = new int[nums.length - k + 1];
        //双端队列
        Deque<Integer> queue = new LinkedList<>();
        //初始化队列
        queue.offer(0);
        int p =0;
        for(int i = 0;i < nums.length;i++){
            //移除不在窗口内的元素(队列头)
            while(!queue.isEmpty() && queue.peekFirst() < i -k +1){
                queue.pollFirst();
            }
            //保持窗口内的元素递减(队列尾),确保队列中的元素是递减的
            while(!queue.isEmpty() && nums[queue.peekLast()] < nums[i]){
                queue.pollLast();
            }
            //添加元素索引
            queue.offer(i);
            //窗口的大小满足k后才能寻找最大值
            if(i >= k -1){
                data[p++] = nums[queue.peekFirst()];
            }
        }
        return data;
    }
}

4.总结

        这道题用暴力的方法也是可以解决的,但是我觉得采用双端队列来解决会更好。使用双端队列解题的难点,在于要记得及时将已经不在窗口内的元素移除和在添加新元素索引之前,要把无法保持递减的元素索引移除。好了,这道题就讲到这了,祝大家刷题愉快!

标签:Java,nums,--,元素,queue,队列,LeetCode100,滑动,窗口
From: https://blog.csdn.net/2301_79318558/article/details/143362542

相关文章

  • 人体解剖生理学——细胞的生物电活动
     一、细胞的生物电现象1、将记录电极捕人轴突内,将参考电极留于细胞外,两电极连于示波器。在细胞没有受到外来刺激情况下,所记录到的电位值相对于膜外为一负值。这种在安静状态下,存在于细胞股内、外两侧的电们差称静息电位,其特点为“外正内负”。2、静息电位基础上,当细胞受到......
  • 编辑距离 | 动态规划
    设A和B是两个字符串,求将字符串A转换为字符串B的最少操作次数。字符操作共有如下三种:     (1)删除一个字符。     (2)插入一个字符。     (3)将一个字符改为另一个字符。 如A=“kitten”、B=“sitting“,求编辑距离。#include<iostream>#include<cstdio......
  • 毕设选题应当注意什么-如何选题-附相关解决案例资料
    毕设选题应当注意什么-如何选题-附相关解决案例资料计算机相关的学生可以有以下方向可以选择,其他专业的同学可以和我交流选题以下是一些视觉课题的建议,供同学选择作为毕业研究的方向:图像分类与识别:研究如何使用深度学习模型对图像进行分类和识别,探索不同网络架构和训练技......
  • yolo-nas无人机高空红外热数据小目标检测(教程+代码)
    前言YOLO-NAS是目前最新的YOLO目标检测模型。从一开始,它就在准确性方面击败了所有其他YOLO模型。与之前的YOLO模型相比,预训练的YOLO-NAS模型能够以更高的准确度检测更多目标。但是我们如何在自定义数据集上训练YOLONAS?这将是我们本文的目标——在自定义数据集上训......
  • 基于深度学习的停车位关键点检测系统(代码+原理)
    摘要:DMPR-PS是一种基于深度学习的停车位检测系统,旨在实时监测和识别停车场中的停车位。该系统利用图像处理和分析技术,通过摄像头获取停车场的实时图像,并自动检测停车位的位置和状态。本文详细介绍了DMPR-PS系统的算法原理、创新点和实验结果,并对其性能进行了评估。在这里......
  • Java独门秘籍:如何用单例模式炼成“独孤求败”
    前言在江湖之中,“独孤求败”不仅是实力的象征,更是对“绝对”的追求,如同巅峰高手俯瞰四方。转眼来到Java的编程江湖,单例模式恰似那传说中的“独孤求败”,以其无与伦比的威力统领着资源管理的战场。它确保一个类只存在唯一的实例,如同武林至尊般静坐于山巅,稳如泰山,任凭风雨侵袭,依......
  • java.字符流.study
    字节流适合文档文件的复制,而字符流适合文本的读取。         ......
  • Sentinel学习圣经:从入门到精通 Sentinel,最全详解 (40+图文全面总结)
    文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录博客园版为您奉上珍贵的学习资源:免费赠送:《尼恩Java面试宝典》持续更新+史上最全+面试必备2000页+面试必备+大厂必备+涨薪必备免费赠送:《尼恩技术圣经+高并发系列PDF》,帮你实现技术自由,完成职业升级,薪......