leetcode-239.滑动窗口最大值

双端队列


题目详情

给你一个整数数组 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]

思路:
我们可以利用双端队列进行操作:每当向右移动时,把窗口左端的值从队列左端剔除,把队
列右边小于窗口右端的值全部剔除。
这样双端队列的最左端永远是当前窗口内的最大值。
另外,这道题也是单调栈的一种延申:该双端队列利用从左到右递减来维持大小关系。

我的代码:

class Solution 
{
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) 
    {
       deque<int> dq;   //双端队列(保存递减元素的索引而非元素值)
       vector<int> ans;   //答案vector  
       //遍历nums
       //注意要实现滑动窗口,就要保证每次窗口内的元素个数都为k个
       for (int i = 0; i < nums.size(); ++i) 
       {
           //下面的第一个if和while用来实现两个筛选条件--队首出队+队右小元素出队
           //第一次不会执行因为dq为空
           
           //dq.front()(最大值在nums中的索引)

           //dq.front() == i - k说明当前以i结尾的滑动窗口已经不包括dq.front()了(这里我迷糊了一下)
           //因为如果包括的话,就应该是dq.front()+1 == i - k
           //例如假设最大值索引为0,现在遍历到了末尾索引3的,那么3-3=0但是窗口中却已经有0123四个元素了
           //所以需要满足dq.front()+1 == i - k
           if (!dq.empty() && dq.front() == i - k) 
           {
               dq.pop_front(); //窗口后移了,最大值索引不在窗口中了,故让其出队
           }
           //队尾往前while,小于新窗口右端(新push的元素)的都出队
           //(保证新元素下标插入队列位置正确--左边没有小于它的)
           while (!dq.empty() && nums[dq.back()] < nums[i])
           {
               dq.pop_back();
           }
           dq.push_back(i); //将新元素下标插入队列
           //i >= k - 1是为了确保 dq.front() 至少为第一个完整的滑动窗口的最大值索引。
           //即至少初次形成了一个完整的滑动窗口。
           if (i >= k - 1)  
           {
               ans.push_back(nums[dq.front()]); //每次循环都记录一次队首即为最大值
           }
       }  
       return ans;
    }
};

本题关键在于我们要用双端队列模拟出一个队首始终记录最大元素,
怎么实现呢,那就每次移动窗口对应两种筛选条件:
1.当队首不在滑动窗口中时,front.pop()
2.每次push元素都要看前面有没有比其小的元素从而将其pop_back
这样双端队列中始终是递减的顺序
因为我们要执行pop和push,还要在nums中提取最大的元素存入ans
所以我们选择利用deque存储元素的索引而非元素本身

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ggaoda

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值