最初想法(错误)
思想:使用单调栈+滑动窗口的方式,首先先初始化一个单调递增栈这个单调递增栈的大小为k,这样可以第一个窗口中的最大值,会位于当前单调递增栈的栈顶,可以直接记录进入最终返回的vector,然后开始进行滑动窗口,设置l,r两个变量记录窗口的左右边界,分别初始化为0和k-1。然后每次将l++,r++,比较加入的nums[r]与栈顶元素的关系。如果大于元素,则入栈,并且将nums[r]加入最终的vector,如果小于,则将当前栈顶元素加入最终vertor。
显然,在这种思路中我忽视了对于过期元素的处理(即不在当前窗口内的元素可能在栈顶出现的问题)
#include<iostream>
#include<vector>
#include<stack>
using namespace std;
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> ans; // 最终返回的ans
stack<int> st; // 需要维护的单调递增栈
// 初始话第一个单调递增栈
st.push(nums[0]);
for(int i=1;i<k;i++){
if(nums[i]>nums[i-1]) st.push(nums[i]);
}
ans.push_back(st.top());
int l=0,r=k-1;
while(r<nums.size()){
l++;r++;
if(nums[r]>st.top()){
st.push(nums[r]);
}
ans.push_back(st.top());
}
return ans;
}
};
解法二:双端队列+滑动窗口
虽然上述解法出现错误,但主要是在栈对于过期元素的处理不方便上,于是,我考虑了使用双端队列来完成上述思路。申请一个双端队列,用于维护当前窗口,每次加入一个窗口元素时,都先去除掉队列中小于当前插入元素的元素,这样能够维护队列的单调性,保证最大元素一直在队头,当循环变量i到达k-1之后,每一次都需要对最终的返回vector进行插入双端队列的队头元素。但是要先检查对头元素是在当前窗口内的,所以我们最好在存储双端队列时,存入的时,该元素在数组中的索引。
#include<iostream>
#include<vector>
#include<deque>
using namespace std;
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> ans; // 最终返回的ans
deque<int> dq; // 需要维护的双端队列
for(int i=0;i<nums.size();i++){
// 判断当前对头元素是否属于当前窗口
if(!dq.empty()&&dq.front()<i-k+1){
dq.pop_front();
}
// 清理当前队中小于当前需要插入元素的元素
while(!dq.empty()&&nums[dq.back()]<nums[i]){
dq.pop_back();
}
// 插入当前元素至队尾
dq.push_back(i);
// 当窗口达到k时开始统计最终的ans
if(i>=k-1){
ans.push_back(nums[dq.front()]);
}
}
return ans;
}
};
时间:O(n*k)最坏,当队列为递减队列时
空间:O(k) 用于维护双端单调队列
官方解法:
1.优先队列+滑动窗口
由于优先队列默认使用大根堆的方式存储,所以每次只需要判断当前的对丁元素是否在窗口内即可,如果不在就出队,在的话,当前窗口的最大值就是队顶元素,其实本质上思路与我的思路类似,不过他选择了一种更加适合的数据结构,可见熟练掌握并运用stl的重要性。
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
int n = nums.size();
priority_queue<pair<int, int>> q;
for (int i = 0; i < k; ++i) {
q.emplace(nums[i], i);
}
vector<int> ans = {q.top().first};
for (int i = k; i < n; ++i) {
q.emplace(nums[i], i);
while (q.top().second <= i - k) {
q.pop();
}
ans.push_back(q.top().first);
}
return ans;
}
};
作者:力扣官方题解
链接:https://leetcode.cn/problems/sliding-window-maximum/solutions/543426/hua-dong-chuang-kou-zui-da-zhi-by-leetco-ki6m/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
时间:O(nlogn)
空间:O(n)
官方解二与我的解类似。
官方解三太妙了,没怎么看懂。