#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