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

滑动窗口最大值

给你一个整数数组 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 <= numsi <= 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()//在指定位置删除元素

相关推荐
JieE21211 小时前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
Jack2019 小时前
HarmonyOS开发中错误处理策略:网络异常统一处理
算法
小小杨树21 小时前
读懂色彩:拍照调色不再难
算法·计算机视觉·配色
JieE2122 天前
LeetCode 226. 翻转二叉树|JS 递归超详细拆解,二叉树入门经典题
javascript·算法
JieE2122 天前
LeetCode 104. 二叉树的最大深度|递归思路超详细拆解
javascript·算法
vivo互联网技术2 天前
CVPR 2026 | 全新强化学习框架 BeautyGRPO:重塑真实人像
算法·大模型·cvpr·影像
Darling噜啦啦2 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
用户497863050732 天前
(一)小红的数组操作
算法·编程语言
怕浪猫2 天前
Electron 系列文章封面图
算法·架构·前端框架