【做一道算一道】滑动窗口最大值

滑动窗口最大值

给你一个整数数组 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

思路

点了。

记得之前看过好像,但是没做出来。

记得思路是用队列来维护滑动窗口,保持每次访问和对比的是窗口中的最大值,但是具体实现的细节记不住,没写出来。

用单调队列,保证队列递减,新添加进的窗口中的值必须比之前添加的值都小,否则,将队列清空。保证最前面的元素是窗口最大值,便于记录和比较。

细节:

1.i和j的值:

因为j和i是数组的索引,所以j-i+1=k,即滑动窗口的大小。而初始值中,j=0(从第一个元素开始,从右端开始滑动)所以确定i的初始值是i=1-k。

2.删除队列元素

两种元素需要删除,一种是滑动过程中离开了窗口的值,一种是单调队列(窗口)中新进入的值比原先的都大时需要清空队列。

一、i是窗口的最左端,在滑动过程中也是跟着移动的,所以i++是必要的,不同于别的一些滑动窗口的题。i>0是为了防止有重复元素的情况下误删,i=0了之后说明第一个窗口建立。i>0则说明开始移动了第一次,这个时候队列最前面的元素(也就是最大值)等于索引i-1(离开窗口了)的元素值,说明该元素需要弹出。

二、新添加进的窗口中的值必须比之前添加的值都小,否则,将队列清空。保证最前面的元素是窗口最大值,便于记录和比较。

代码

cpp 复制代码
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        if(nums.size() == 0 || k == 0) return {};
        deque<int> deque;
        vector<int> res(nums.size() - k + 1);
        for(int j = 0, i = 1 - k; j < nums.size(); i++, j++) {
            // 删除 deque 中对应的 nums[i-1]
            if(i > 0 && deque.front() == nums[i - 1])
                deque.pop_front();
            // 保持 deque 递减
            while(!deque.empty() && deque.back() < nums[j])
                deque.pop_back();
            deque.push_back(nums[j]);
            // 记录窗口最大值
            if(i >= 0) //i=0开始建立起窗口
                res[i] = deque.front();
        }
        return res;
    }
    
};

队列(queue)常用函数:

push() 在队尾插入一个元素

pop() 删除队列第一个元素

size() 返回队列中元素个数

empty() 如果队列空则返回true

front() 返回队列中的第一个元素

back() 返回队列中最后一个元素

单调队列(deque)常用函数:

push_back()//在队列的尾部插入元素。

emplace_front()//与push_front()的作用一样

push_front()//在队列的头部插入元素。

emplace_back()//与push_back()的作用一样

pop_back()//删除队列尾部的元素。

pop_front()//删除队列头部的元素。

back()//返回队列尾部元素的引用。

front()//返回队列头部元素的引用。

clear()//清空队列中的所有元素。

empty()//判断队列是否为空。

size()//返回队列中元素的个数。

begin()//返回头位置的迭代器

end()//返回尾+1位置的迭代器

rbegin()//返回逆头位置的迭代器

rend()//返回逆尾-1位置的迭代器

insert()//在指定位置插入元素

erase()//在指定位置删除元素

相关推荐
drylong3 分钟前
困难 - 2999. 统计强大整数的数目
算法
小美爱刷题18 分钟前
力扣DAY40-45 | 热100 | 二叉树:直径、层次遍历、有序数组->二叉搜索树、验证二叉搜索树、二叉搜索树中第K小的元素、右视图
数据结构·算法·leetcode
冷月半明31 分钟前
Prophet预测波动性实战:5招让你的时间序列曲线"活"起来 破解预测曲线太平滑的行业痛点
后端·算法·机器学习
Ayanami_Reii1 小时前
NOIP2011提高组.玛雅游戏
算法·游戏·深度优先
_extraordinary_1 小时前
笔试专题(六)
算法·哈希算法·贪心·模拟·滑动窗口·构造
学习编程的gas1 小时前
数据结构——堆的实现和堆排序
数据结构·算法
claude61 小时前
实测文心4.5与X1一个月后,我预测文心大模型4.5 Turbo将有这几个升级点
算法
jz_ddk2 小时前
[实战]多天线空域抗干扰技术:原理、数学推导与工程仿真(完整仿真代码)
python·算法·毕业设计·信号处理
Determined_man2 小时前
Mybatis-plus queryWrapper的使用
数据结构·数据库
dog shit2 小时前
蓝桥杯第十一届省赛C++B组真题解析
算法