920-滑动窗口的最大值

题目如下

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

返回滑动窗口中的最大值。

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

示例:
输入: 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

解题思路

我们可以采用队列,DP,堆等方式进行求解,所有思路的主要源头应该都是在窗口滑动的过程中,如何更快的完成查找最大值的过程。但是最典型的解法还是使用双端队列。具体怎么来求解,一起看一下。

首先,我们了解一下,什么是双端队列:是一种具有队列和栈的性质的数据结构。双端队列中的元素可以从两端弹出或者插入。
在这里插入图片描述
我们可以利用双端队列来实现一个窗口,目的是让该窗口可以做到张弛有度(汉语博大精深,也就是长度动态变化。其实用游标或者其他解法的目的都是一样的,就是去维护一个可变长的窗口)

然后我们再做一件事,只要遍历该数组,同时在双端队列的头去维护当前窗口的最大值(在遍历过程中,发现当前元素比队列中的元素大,就将原来队列中的元素删除出队),在整个遍历的过程中我们再记录下每一个窗口的最大值到结果数组中。最终结果数组就是我们想要的,整体图解如下。

假设 nums = [1,3,-1,-3,5,3,6,7],和 k = 3
在这里插入图片描述

解题代码

#include <iostream>
#include <vector>
#include <deque>
using namespace std;

vector<int> maxInWindows(const vector<int>& num, unsigned int size) 
{
    vector<int> result;
    if (num.size() >= size && size >= 1) 
    {
        deque<int> numDeque;
        //首先把前size个数按照规则压入双向队列
        for (int i = 0; i != size; i++) 
        {
            while (!numDeque.empty() && num[i] >= num[numDeque.back()]) 
            {
                numDeque.pop_back();
            }
            numDeque.push_back(i);
        }
        //压入第一个最大值
        //滑动窗口的最大值总是位于双向队列的头部
        result.push_back(num[numDeque.front()]);
        for (int i = size; i != num.size(); i++) 
        {
            //首先按照规则压入新的值
            while (!numDeque.empty() && num[i] >= num[numDeque.back()])
            {
                numDeque.pop_back();
            }
            //并且删除旧值,即滑出了窗口的值
            if (!numDeque.empty() && numDeque.front() <= static_cast<int>(i - size)) 
            {
                numDeque.pop_front();//出队
            }
            numDeque.push_back(i);
            result.push_back(num[numDeque.front()]);
        }
    }
    return result;
}

int main()
{
    vector<int> data{ 2,3,4,2,6,2,5,1 };
    vector<int> result = maxInWindows(data, 3);
    for (auto a : result)
    {
        cout << a << " ";
    }
    cout << endl;

    return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

林林林ZEYU

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

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

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

打赏作者

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

抵扣说明:

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

余额充值