力扣
1.暴力解法,时间复杂度O(n * k)
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k)
{
//暴力算法
//窗口边界
int left = 0;
int right = k-1;
vector<int> ret;
for(int i = k ; i <= nums.size();++i)
{
int max = nums[left];
for(int j = left+1 ; j <= right ;++j) //计算每个窗口的最大值
{
if(nums[j] > max)
{
max = nums[j];
}
}
ret.push_back(max);
++left;
++right;
}
return ret;
}
};
2.单调栈,时间复杂度O(n)
①思路
- 滑动窗口移动就像队列,头出,尾入
- 使用deque(双端队列,头尾的增加删除都是O(1)) , 只要遍历该数组,同时在双端队列的头去维护当前窗口的最大值(在遍历过程中,发现当前元素比队列中的元素大,就将原来队列中的元素移出),在整个遍历的过程中我们再记录下每一个窗口的最大值到结果数组中
- 在deque中我们存的是元素对应数组的下标
②图示理解
图片来自 : 小浩算法
③代码
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k)
{
//单调栈
deque<int> dq;
vector<int> ret;
//nums.size()个数依次入队
for(int i = 0 ; i < nums.size();++i)
{
//每添加一个数据,都要保证队列是递减的 :如果前面的数字小就要持续pop
//nums[dq.back()] <= nums[i] ,即使数据相同也pop掉,因为已经用过一次了,我们要用最新的
while(!dq.empty() && nums[dq.back()] <= nums[i] )
{
dq.pop_back();
}
//元素入队,前面已经保证是降序了
dq.push_back(i);
//如果队列的最大值下标 <= i-k 即最大值不在有效的数组范围中,这个最大值无效
if(dq.front() <= i-k)
{
dq.pop_front();
}
//前k个数组成一组后才开始计算每一组的最大值
if(i >= k-1)
{
ret.push_back(nums[dq.front()]);
}
}
return ret;
}
};
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k)
{
deque<int> dq;
vector<int> ret;
for (int i = 0 ; i < nums.size() ;++i)
{
while (!dq.empty() && i-k >= dq.front()) dq.pop_front();
while (!dq.empty() && nums[i] >= nums[dq.back()]) dq.pop_back();
dq.push_back(i);
if (i >= k-1)
ret.push_back(nums[dq.front()]);
}
return ret;
}
};