首页 > 其他分享 >【剑指Offer】64、滑动窗口的最大值

【剑指Offer】64、滑动窗口的最大值

时间:2023-08-24 22:33:26浏览次数:32  
标签:窗口 数字 Offer 队列 最大值 num 64 滑动

【剑指Offer】64、滑动窗口的最大值

题目描述:

给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

解题思路:

如果不考虑时间开销,使用蛮力法,本题并不难解决,依次遍历所有的滑动窗口,扫描每个窗口中的所有数字并找出其中的最大值,这都很容易实现,但是如果滑动窗口的大小为k,那么需要O(k)的时间找最大值,对于长度为n大的数组,总的时间复杂度为O(nk)。

然后我们考虑进一步优化,一个滑动窗口实际上可以看成一个队列。当窗口滑动时,处于窗口第一个位置的数字被删除,同时在窗口的末尾又增加了一个新的数字。这符合队列“先进先出”的特性。

在第20题:包含min函数的栈,我们使用两个栈实现了一个求最小值的栈,在O(1)时间内可以得到最小值,这里我们可以改为求最大值,同样可以在O(1)时间内得到最大值,而这里的数据用队列保存,我们可以用两个栈实现队列,这就是第5题:用两个栈实现队列。这样,实际上综合这两题我们可以解决本题,总的时间复杂度也可以降到O(n)。

这里我们换用另外一种方法:使用双端队列。我们不把所有的值都加入滑动窗口,而是只把有可能成为最大值的数加入滑动窗口。这就需要一个两边都可以操作的双向队列。

我们以数组{2,3,4,2,6,2,5,1}为例,滑动窗口大小为3,先把第一个数字2加入队列,第二个数字是3,比2大,所以2不可能是最大值,所以把2删除,3存入队列。第三个数是4,比3大,同样删3存4,此时滑动窗口以遍历三个数字,最大值4在队列的头部。

第4个数字是2,比队列中的数字4小,当4滑出去以后,2还是有可能成为最大值的,因此将2加入队列尾部,此时最大值4仍在队列的头部。

第五个数字是6,队列的数字4和2都比它小,所以删掉4和2,将6存入队列尾部,此时最大值6在队列头部。

第六个数字是2,此时队列中的数6比2大,所以2以后还有可能是最大值,所以加入队列尾部,此时最大值6在仍然队列头部。

······

依次进行,这样每次的最大值都在队列头部。

还有一点需要注意的是:如果后面的数字都比前面的小,那么加入到队列中的数可能超过窗口大小,这时需要判断滑动窗口是否包含队头的这个元素,为了进行这个检查,我们可以在队列中存储数字在数组中的下标,而不是数值,当一个数字的下标和当前出来的数字下标之差大于等于滑动窗口的大小时,这个元素就应该从队列中删除。

举例:

编程实现(Java):

import java.util.*;
public class Solution {
    public ArrayList<Integer> maxInWindows(int [] num, int size){
        /*
        思路:用双端队列实现
        */
        ArrayList<Integer> res=new ArrayList<>();
        if(num==null || num.length<1 || size<=0 || size>num.length)
            return res;
        Deque<Integer> queue=new LinkedList<>();
        for(int i=0;i<num.length;i++){
            while(!queue.isEmpty() && queue.peek()<i-size+1) //超出范围的去掉
                 queue.poll();
            //当前值大于之前的值,之前的不可能是最大值,可以删掉
            while(!queue.isEmpty() && num[i]>=num[queue.getLast()]) 
                 queue.removeLast();
            queue.add(i);
            if(i>=size-1){ //此时开始是第一个滑动窗口
                res.add(num[queue.peek()]);
            }
        }
        return res;
    }
}

标签:窗口,数字,Offer,队列,最大值,num,64,滑动
From: https://www.cnblogs.com/bujidao1128/p/17655324.html

相关文章

  • 【剑指Offer】63、数据流中的中位数
    【剑指Offer】63、数据流中的中位数题目描述:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用Ge......
  • 《剑指Offer》-60-n 个骰子的点数
    打印出n个骰子所能扔出的所有点数的概率思路dp[i][j]表示i个骰子,投出j的概率而概率=点数出现的次数/总次数而i个骰子掷出j的次数=i-1个骰子掷出j-1的次数+i-1个骰子掷出j-2的次数+…+i-1个骰子掷出j-6的次数,因为这个单独的骰子能掷......
  • 【剑指Offer】46、圆圈中最后剩下的数
    【剑指Offer】46、圆圈中最后剩下的数题目描述:每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报......
  • js_使用axios请求图片资源, 并读取图片资源为base64格式
    情景再现:今天在写页面时遇到这么一个请求:有一张图片,默认隐藏,要求在该图片加载完毕后,执行取消隐藏的动画.目的是不要在执行动画期间图片有空白的样子.第一个想到的当然是img的onload回调函数.但是天生反骨不爱用行内元素.于是想到使用ajax请求图片资源,再使用FileR......
  • 剑指 Offer 47. 礼物的最大价值(中等)
    题目:classSolution{public:intmaxValue(vector<vector<int>>&grid){if(grid.empty())return0;//要考虑棋盘为空的情况直接返回0vector<vector<int>>dp(grid.size(),vector(grid[0].size(),0));//定义一个和棋盘同样大小的dp......
  • 剑指 Offer 63. 股票的最大利润(中等)
    题目:classSolution{public:intmaxProfit(vector<int>&prices){if(prices.empty())return0;//要考虑数组为空的情况vector<vector<int>>dp(prices.size(),vector<int>(2,0));//确定动态数组大小和下表含义dp[i][j]:第i天j状态......
  • 手算base64
    CSP2021考了……什么鬼……base64是什么Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。可查看RFC2045~RFC2049,上面有MIME的详细规范。Base64编码是从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信......
  • 2064:【例2.1】交换值
    2064:【例2.1】交换值时间限制:1000ms      内存限制:65536KB提交数:114708   通过数:62617【题目描述】输入两个正整数a和b,试交换a、b的值(使a的值等于b,b的值等于a)。【输入】输入两个正整数a和b。【输出】输出a与b交换值后的结果。【输入样例】......
  • 【Python】pandas操作, 取最大值, 最小值, 平均值, 生成 空值, 多个 series合并, 替换
    1.取最大值,最小值,平均值df.max()df.iloc[:,1:].max()df.min()df.mean()#输出indexvalue2.生成空值,带index的seriespd.Series(index=['1','2','3'],dtype='object')"""1NaN2NaN3NaNdtype:objec......
  • Base64编码和解码
    1、依赖sun.misc.BASE64Decoder.jar/***Base64编码*@paramdata要加密的字符数组*@returnString加密后的16进制字符串*/publicstaticStringencode(byte[]data){returnnewBASE64Encoder().encode(data);}/***Base64解码*@paramdata要解密......