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

滑动窗口最大值

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

相关推荐
冉佳驹1 小时前
数据结构 ——— 快速排序的时间复杂度以及规避最坏情况的方法
c语言·数据结构·算法·排序算法·快速排序算法·三数取中
徐浪老师2 小时前
C语言实现冒泡排序:从基础到优化全解析
c语言·算法·排序算法
hr_net2 小时前
图论入门编程
算法·图论
李小白662 小时前
各种排序算法
数据结构·算法·排序算法
浪前2 小时前
排序算法之冒泡排序篇
数据结构·算法·排序算法
小黄编程快乐屋2 小时前
各个排序算法基础速通万字介绍
java·算法·排序算法
PeterClerk2 小时前
图论基础知识
算法·深度优先·图论
是糖不是唐2 小时前
代码随想录算法训练营第五十八天|Day58 图论
c语言·算法·图论
Eric.Lee20214 小时前
数据集-目标检测系列- 装甲车 检测数据集 armored_vehicles >> DataBall
python·算法·yolo·目标检测·装甲车检测
慢慢来_6 小时前
【力扣热题100】[Java版] 刷题笔记-448. 找到所有数组中消失的数字
笔记·算法·leetcode