滑动窗口动态获取窗口最大值与最小值

滑动窗口

滑动窗口是一种想象出来的数据结构,窗口有左边界L和右边界R。

在数组或者字符串或者一个序列上,记为S,窗口就是S[L…R]这一部分,L往右滑动意味着有样本滑出窗口,R往右划动意味着有样本滑入窗口,L和R都只能往右滑动。

窗口定义
  1. R边界向右移动,数组中的数从窗口右侧进入窗口
  2. L边界向右移动,数组中的数从窗口左侧出窗口
  3. 左边界不能到右边界的右侧
如何找到动态窗口中的最大值
  1. 准备一个双端队列,数据可以从头部进头部出,也可以从尾部进尾部出。
  2. R++时,将数据从双端队列的尾部插入,此时队列为空,可以直接将数组对应元素的索引直接插入。
  3. 双端队列从头到尾按照从大到小的顺序保持,所以当R++,即窗口右边界往右滑动时,窗口内加入新的数,此时需要判断队列的末端的数字是否大于当前数,如果末端数字大于当前数,因为仍然保持大小顺序,所以可以直接将数插入到队列末端。
  4. 如果队列末端数字索引数组的值小于或等于当前数,若直接插入会违反队列中的大小顺序,所以需要将队列末端的数弹出,直到队列为空(可以直接插入)或者末端的数大于当前数(满足大小顺序)。
  5. L++时,即左边界往右移动,此时需要将队列中那些不在窗口中的数剔除,所以当左边界向右移动时,取出队列的头部元素判断是否等于右边界减去窗口宽度的值(因为此时的左边界是R-W+1),若等于,说明队首元素已经过期,需要弹出。
对比遍历法求最大值,分析算法复杂度

L和R需要滑过整个数组,每个位置最多进入一次双端队列,出去一次(两种情况:一种是当前下标过期,从头部出去;另一种是遇到了大于这个数的数,从尾部弹出)。整个过程的时间复杂度O(N),查询某个时刻最大值O(1)。

题目联系leetcode239

思路:维护一个滑动窗口,将双端队列首部的元素不断弹出到结果数组中

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        int R=0;
        int N=nums.size();
        deque<int>dq;
        vector<int>result(N-k+1,0);
        int index=0;
        for(int R=0;R<N;R++){
            while(!dq.empty()&&nums[dq.back()]<=nums[R]){
                dq.pop_back();
            }
            dq.push_back(R);
            if(dq.front()==R-k){
                dq.pop_front();
            }
            if(R>=k-1){
                result[index++]=nums[dq.front()];
            }
        }
        return result;
    }
};
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值