滑动窗口中的最大值

#include <iostream>
#include <vector>
#include <deque>

using namespace std;

//滑动窗口中的最大值
/*
给定一个数组和滑动窗口的大小,
找出所有滑动窗口里数值的最大值。
例如,如果输入数组{2,3,4,2,6,2,5,1}
及滑动窗口的大小3,那么一共存在6个滑动窗口,
他们的最大值分别为{4,4,6,6,6,5};
 针对数组{2,3,4,2,6,2,5,1}
 的滑动窗口有以下6个:
{[2,3,4],2,6,2,5,1},
{2,[3,4,2],6,2,5,1},
{2,3,[4,2,6],2,5,1},
{2,3,4,[2,6,2],5,1},
{2,3,4,2,[6,2,5],1},
{2,3,4,2,6,[2,5,1]}。
*/
/*
解题思路:
双端队列解决该问题,
用队列开头控制窗口大小,
如果窗口大小大于等于窗口大小时,
则删除队列开头元素,
而对于队列尾端用于与输入数据作比较,
如果大于队列尾端元素,
则将尾端元素抛掉,
直到当前元素小于等于尾端元素为止,
这样便能够保证双端队列开头元素值肯定是最大。
*/
//data为数组,size为窗口大小,result为结果(要用引用的形式)
int MaxNums(vector<int> data, int Size, vector<int>& result)
{
    //检查参数
    if (data.empty() || Size <= 1 ||!result.empty())
        return -1;//-1代表程序出现错误

    //创建一个双端队列
    deque<int> dataIndex;

    //先输入开头size个数据
    for (int i = 0; i < Size; i++)
    {
        //当deque队列不为空且最后一个元素小于要插入的元素
        while (!dataIndex.empty() && data[i] >= data[dataIndex.back()])
        {
            dataIndex.pop_back();
        }
        dataIndex.push_back(i);//插入的是这个数据的索引
    }

    //从size个数据开始往后遍历
    for (int i = Size; i < data.size(); i++)
    {
        result.push_back(data[dataIndex.front()]);
        //要插入的数据大于双端队列的队尾,则删除双端队列的队尾
        while (!dataIndex.empty() && data[i] >= data[dataIndex.back()])
        {
            dataIndex.pop_back();//删除双端队列的队尾
        }
        //当前的索引与双端队列的开头元素相差大于等于size时,说明队列开头已经不再窗口中了
        if (!dataIndex.empty() && (i - dataIndex.front()) >= Size)
        {
            //将双端队列中第一个元素移出
            dataIndex.pop_front();
        }
        dataIndex.push_back(i);
    }
    result.push_back(data[dataIndex.front()]);//最后还有一个元素
    return 0;
}

int main()
{
    vector<int> vect{ 2,3,4,2,6,2,5,1,9 };
    int Size = 3;
    vector<int> result;
    if (MaxNums(vect, Size, result) == 0)//返回0,代表正常运行
    {
        for (auto res : result)
        {
            cout << res << endl;
        }
    }
    return 0;
}

滑动窗口中的最大值

参考:https://blog.csdn.net/weixin_39485901/article/details/91493277

上一篇:echars 柱状图点击事件


下一篇:[剑指Offer系列] 52 两个链表的第一个公共节点