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

滑动窗口最大值

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

相关推荐
d111111111d19 分钟前
在STM32函数指针是什么,怎么使用还有典型应用场景。
笔记·stm32·单片机·嵌入式硬件·学习·算法
明洞日记23 分钟前
【数据结构手册008】STL容器完全参考指南
开发语言·数据结构·c++
kingmax5421200839 分钟前
《数据结构C语言:单向链表-链表基本操作(尾插法建表、插入)》15分钟试讲教案【模版】
c语言·数据结构·链表
AI科技星1 小时前
质量定义方程常数k = 4π m_p的来源、推导与意义
服务器·数据结构·人工智能·科技·算法·机器学习·生活
摇摆的含羞草1 小时前
哈希(hash)算法使用特点及常见疑问解答
算法·哈希算法
Fine姐1 小时前
数据结构04——二叉树搜索树BST
数据结构
仰泳的熊猫2 小时前
1077 Kuchiguse
数据结构·c++·算法·pat考试
LYFlied2 小时前
【每日算法】LeetCode 19. 删除链表的倒数第 N 个结点
算法·leetcode·链表
阿里巴巴AI编程社区2 小时前
Qoder 提效实战:数据开发工程师用 Qoder 提效50%
数据结构
踏浪无痕2 小时前
计算机算钱为什么会算错?怎么解决?
后端·算法·面试