该题的思路就是用双端队列来实现滑动窗口;首要要知道的一点是:如果一个滑动窗口出现了新的最大值,那么比它小的旧元素可以全部丢掉,因为这个窗口不会再有比它大的旧元素值,如果出现了新的比最大元素小的,那就放进去,因为最大元素走了之后,该元素可能会是最大元素;同时要记住每个元素的最新的下标看是否在滑动窗口中
1.题目如下:
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
--------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
示例 2:
输入:nums = [1], k = 1
输出:[1]
提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
1 <= k <= nums.length
2.代码如下:
class Solution {
public:
/**思路一:暴力遍历,遍历每个元素的时候找出该元素和后面k-1个元素的最大值,此方法时间复杂度高,超时;O(kn)*/
/*
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> res;
for(int i=0;i<=nums.size()-k;i++){
int maxNum=INT_MIN;
for(int j=0;j<k;j++){
maxNum=max(maxNum,nums[i+j]);
}
res.push_back(maxNum);
}
return res;
}
*/
//思路二:用双端队列来实现单调队列
/*
使得队列中的元素是单调递增的,对手的元素最大,并用哈希表记录每个元素所在的坐标判断队首元素是否在滑动窗口中;
如果有比队首元素更大的数,就清空栈,放入该元素,因为只要有这个数存在,其他之前的数不可能成为最大值
*/
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> qTemp;
vector<int> res;
unordered_map<int,int> idx;
for(int i=0;i<k;i++){
if(qTemp.empty()){
qTemp.push_back(nums[i]);
idx[nums[i]]=i;
}
else{
while(!qTemp.empty()){
//依次弹出较小的数保证是从大到小的
if(nums[i]>=qTemp.back()){
qTemp.pop_back();
}
else{
break;
}
}
qTemp.push_back(nums[i]);
idx[nums[i]]=i;
}
}
res.push_back(qTemp.front());
for(int i=k;i<nums.size();i++){
while(!qTemp.empty()){
if(nums[i]>=qTemp.back()){
qTemp.pop_back();
}
else{
break;
}
}
qTemp.push_back(nums[i]);
idx[nums[i]]=i;
while(i-k+1>idx[qTemp.front()]){
qTemp.pop_front();
}
res.push_back(qTemp.front());
}
return res;
}
};