【第9题】求每次滑动窗口中的最大值(考察队列)
回城传送–》《JAVA筑基100例》
 
零、前言
 今天是学习 JAVA语言 打卡的第9天,每天我会提供一篇文章供群成员阅读( 不需要订阅付钱 ),读完文章之后,按解题思路,自己再实现一遍。在小虚竹JAVA社区 中对应的 【打卡贴】打卡,今天的任务就算完成了。
 因为大家都在一起学习同一篇文章,所以有什么问题都可以在群里问,群里的小伙伴可以迅速地帮到你,一个人可以走得很快,一群人可以走得很远,有一起学习交流的战友,是多么幸运的事情。
 学完后,自己写篇学习报告的博客,可以发布到小虚竹JAVA社区 ,供学弟学妹们参考。
 我的学习策略很简单,题海策略+ 费曼学习法。如果能把这100题都认认真真自己实现一遍,那意味着 JAVA语言 已经筑基成功了。后面的进阶学习,可以继续跟着我,一起走向架构师之路。
一、题目描述
原题地址–》传送门
 题目: 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
 示例:
 
二、解题思路
-  先了解什么是滑动窗口:先按示例1的数组来,窗口长度是3,窗口是向右移动,相当于是从数组的下标从0开始递增。增到下标为2时,满足窗口长度(这时窗口就形成了),然后计算窗口里3个数据的最大值。 
 得到最大值后,窗口再向右移到一格,再计算窗口里3个数据的最大值。
 直到数组的最后一个元素形成的窗口比较完成,滑动窗口结束。
-  对于求**的最大值,我们可优先考虑队列来做 
-  创建个数组result 用来保存每个窗口的最大值 
-  本题用双向队列来实现,使用LinkedList 存储数组的下标 
-  定义一个变量:rightIndex,表示滑动窗口右边界 
-  定义一个变量:leftIndex,表示滑动窗口左边界 
-  遍历数组 - 用while循环,当队列非空时,数组滑动新的元素大于等于队尾的元素,则队尾的元素移掉,因为不是最大值;while循环结果条件,队列空了,或者数组滑动新的元素小于队尾的元素
- 把数组滑动新的元素添加到LinkedList 中
- 计算窗口左侧边界leftIndex
- 队首的元素是整个窗口里最大的,但是当数组滑动时,队首的元素已经不在窗口内,就要移除掉
- 因为数组的下标是从0开始,只有窗口右边界的下标+1>=k的值时,才能比较取窗口的最大值(队首的元素)
- 把队首元素保存到result 中。
- 最后把结果输出即可。
 
三、代码详解
package com.xiaoxuzhu;
import java.util.LinkedList;
/**
 * Description: 求每次滑动窗口中的最大值(考察队列)
 *
 * @author zenghw
 * @version 1.0
 *
 * <pre>
 * 修改记录:
 * 修改后版本	        修改人		修改日期			修改内容
 * 2022/8/20.1	    zenghw		2022/8/20		    Create
 * </pre>
 * @date 2022/8/20
 */
class Solution {
    public static void main(String[] args) {
        int[] nums =new int[]{1,3,-1,-3,5,3,6,7};
        int k =3;
        int[] maxs =  maxSlidingWindow(nums,k);
        for (int max : maxs) {
            System.out.println(max);
        }
    }
    public static int[] maxSlidingWindow(int[] nums, int k) {
        // 用来保存每个窗口的最大值
        int[] result = new int[nums.length - k + 1];
        //本题用双向队列来实现,存储数组的下标
        LinkedList<Integer> queueLinkedList = new LinkedList<>();
        // 数组的下标从0开始,遍历数组,rightIndex表示滑动窗口右边界
        for(int rightIndex = 0; rightIndex < nums.length; rightIndex++) {
            // 用while循环,当队列非空时,数组滑动新的元素大于等于队尾的元素,则队尾的元素移掉,因为不是最大值
            // while循环结果条件,队列空了,或者数组滑动新的元素小于队尾的元素
            while (!queueLinkedList.isEmpty() && nums[rightIndex] >= nums[queueLinkedList.peekLast()]) {
                queueLinkedList.removeLast();
            }
            // 存储数组右划的下标
            queueLinkedList.addLast(rightIndex);
            // 计算窗口左侧边界
            int leftIndex = rightIndex - k +1;
            // 队首的元素是整个窗口里最大的,但是当数组滑动时,队首的元素已经不在窗口内,就要移除掉
            if (queueLinkedList.peekFirst() < leftIndex) {
                queueLinkedList.removeFirst();
            }
            // 因为数组的下标是从0开始,只有窗口右边界的下标+1>=k的值时,才能比较取窗口的最大值(队首的元素)
            if (rightIndex +1 >= k) {
                result[leftIndex] = nums[queueLinkedList.peekFirst()];
            }
        }
        return result;
    }
}
  
 
 - 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56

四、推荐专栏
五、示例源码下载
关注下面的公众号,回复筑基+题目号
筑基09
文章来源: xiaoxuzhu.blog.csdn.net,作者:小虚竹,版权归原作者所有,如需转载,请联系作者。
原文链接:xiaoxuzhu.blog.csdn.net/article/details/126438902
- 点赞
- 收藏
- 关注作者
 
            
 
           
评论(0)