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

滑动窗口最大值

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

相关推荐
多喝开水少熬夜29 分钟前
Trie树相关算法题java实现
java·开发语言·算法
WBluuue44 分钟前
数据结构与算法:树上倍增与LCA
数据结构·c++·算法
bruk_spp1 小时前
牛客网华为在线编程题
算法
lkbhua莱克瓦241 小时前
Java基础——集合进阶用到的数据结构知识点1
java·数据结构·笔记·github
杨福瑞2 小时前
数据结构:单链表(2)
c语言·开发语言·数据结构
王璐WL2 小时前
【数据结构】单链表及单链表的实现
数据结构
黑屋里的马3 小时前
java的设计模式之桥接模式(Bridge)
java·算法·桥接模式
z187461030033 小时前
list(带头双向循环链表)
数据结构·c++·链表
sin_hielo3 小时前
leetcode 1611
算法·leetcode
李小白杂货铺3 小时前
识别和破除信息茧房
算法·信息茧房·识别信息茧房·破除信息茧房·算法推荐型茧房·观点过滤型茧房·茧房