/**
* Index: 239
* Title: Sliding Window Maximum
* Author: ltree98
**/
题意
给定一个数组,
有一个长度为k的窗口从数组头部开始向后滑动,每次滑动1位;
输出每次窗口内最大值序列。
注意:
- k保证是合法的,即 k >= 1 且 k <= 数组长度
数组不会为空测试样例中存在数组为空的情况
我的
多队列
也不知道叫多队列合不合适,
最开始的想法就是创建 n - k + 1 个队列(n为数组长度,k为窗口大小),
然后,把相应数分配给相应队列,一个数是可以在多个队列进行比较的。
比如,数组为 1 3 -1 -3 5 3 6 7 ; 窗口大小为3
创建6个队列(8 - 3 + 1)
i(数组序号) 要塞入的队列序号
0 -2,-1,0
1 -1,0, 1
2 0, 1, 2
3 1, 2, 3
4 2, 3, 4
5 3, 4, 5
6 4, 5, 6
7 5, 6, 7
然后前面的-2,-1 和后面的 6, 7 是不存在的队列,过滤掉即可。
因为每个队列其实只需要存一个最大值,所以就没有生成队列,而是用一个最大值来替代。
时间复杂度:O(n*k)
空间复杂度:O(n)
双端队列
利用双端队列的特性,
对于数组内的每个数,将队列从后遍历,将小于这个数的都弹出队列;
将该数收入队列;
记录到当前位置的窗口最大值,
对于超过窗口的弹出队头。
时间复杂度:O(n)
空间复杂度:O(n)
实现
多队列
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
if(k <= 1)
return nums;
int len = nums.size();
vector<int> ans(len - k + 1, INT_MIN);
for(int i = 0; i < len; i++) {
int startIndex = i - k + 1;
for(int j = 0; j < k; j++) {
int ansIndex = startIndex + j;
if(ansIndex >= 0 && ansIndex < (len - k + 1)) {
if(ans[ansIndex] < nums[i])
ans[ansIndex] = nums[i];
}
}
}
return ans;
}
};
双端队列
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
if(k <= 1)
return nums;
int len = nums.size();
deque<int> q;
vector<int> ans;
for(int i = 0; i < len; i ++) {
while(!q.empty() && q.back() < nums[i])
q.pop_back();
q.push_back(nums[i]);
if(i >= k - 1) {
ans.push_back(q.front());
if(q.front() == nums[i - k + 1])
q.pop_front();
}
}
return ans;
}
};
进阶
没看到什么更好的解决方案,基本都是用双端队列来实现。