[LeetCode][C++]滑动窗口最大值

    技术2024-11-08  6

    滑动窗口最大值

    给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回滑动窗口中的最大值。

    进阶: 你能在线性时间复杂度内解决此题吗?

    示例: 输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3 输出: [3,3,5,5,6,7]

    解释: 滑动窗口的位置 \quad 最大值


    [1 3 -1] -3 5 3 6 7 \qquad 3 1 [3 -1 -3] 5 3 6 7 \qquad 3 1 3 [-1 -3 5] 3 6 7 \qquad 5 1 3 -1 [-3 5 3] 6 7 \qquad 5 1 3 -1 -3 [5 3 6] 7 \qquad 6 1 3 -1 -3 5 [3 6 7] \qquad 7

    提示: 1 <= nums.length <= 10^5 -10^4 <= nums[i] <= 10^4 1 <= k <= nums.length


    思路: 总结其他的博客。

    使用双端队列(deque)存储滑动窗口里元素的下标,且保证队首为当前窗口里面的最大元素的索引,尾部用于与当前要压入的元素比较。对于第一个窗口,里面元素为num[0]~num[k-1],每次要押入一个下标i,将num[i]与双端队列(deque)尾部索引对应的元素比较,若小于,则将尾部弹出,一直到遇到大于的,此时则将下标i压入双端队列尾部,因为在双端队列头部弹出去后,此下标有可能为后面窗口的最大值。对于后续窗口,我们在更新双端队列的时候,还需要判断队列的头部是不是在窗口内,即deque.top()>=i-k。每次循环,deque的头部即为该次滑动框里面最大值的索引。

    代码:

    class Solution { public: vector<int> maxSlidingWindow(vector<int>& nums, int k) { vector<int> res; //存放结果 if(nums.size() == 0 || k <= 0 || k > nums.size()) //对给定的数据进行判断,没意义就返回空集 return res; deque<int> max_idx; //创建双端队列,头文件#include <deque> //第一个滑动窗口 for(int i=0;i<k;i++) { while(!max_idx.empty() && nums[i]>= nums[max_idx.back()]) //判断当前元素与双端队列尾部元素大小 { max_idx.pop_back(); } max_idx.push_back(i); //碰到比当前元素大的,就压入当前元素索引 } res.push_back(nums[max_idx.front()]); //保存第一个框的最大值 //后续的框,增加了一个判断条件,双端队列的头部是否在框内 for(int i=k; i<nums.size();i++) { while(!max_idx.empty() && nums[i]>=nums[max_idx.back()]) max_idx.pop_back(); if(!max_idx.empty() && max_idx.front() <= (i-k) ) //不在框内,则将头部弹出。 max_idx.pop_front(); max_idx.push_back(i); res.push_back(nums[max_idx.front()]); //保存每个框的最大值 } return res; } };

    结果:

    参考链接: [1] Zolewit:滑动窗口最大值/C++

    Processed: 0.022, SQL: 9