难度困难
给你一个整数数组 nums
,有一个大小为 k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k
个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值。
思路一:在滑动窗口内保证为单调队列
单调递减队列:在队列中 假定 num[i] ≥ num[j](其中 i < j )。
在上述单调递减队列中的最大元素一定在队列的左侧。
如何确保单调递减队列:需要采用双向队列(deque) 。
- 当前数据小于上一个数据:直接压入队列;
- 当前数据大于上一个数据:将队列中小于该数据的全部数据弹出队列;
- 确保队列中的全部数据在当前窗口内;
- 当期窗口的最大值为当前单调队列的第一个数据(最早的数据)。
代码
// 单调队列实现 - 双端队列
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
if(k==1) return nums;;
int len=nums.size();
deque<int> data;
for(int i=0;i<k;++i){
while(!data.empty() && nums[i]>=nums[data.back()]){
data.pop_back();
}
data.push_back(i);
}
vector<int> ans = {nums[data.front()]};
for(int i=k;i<len;++i){
while(!data.empty() && nums[i]>=nums[data.back()]){
data.pop_back();
}
data.push_back(i);
while(data.front()<=i-k){
data.pop_front();
}
ans.push_back(nums[data.front()]);
}
return ans;
}
思路二:最大堆实现
采用最大堆实现时将每个数压入最大堆中,同时确保当前最大值在窗口范围内,否则弹出当前最大值。
代码
// 最大堆方式实现
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
if(k==1) return nums;;
int len=nums.size();
priority_queue<pair<int, int>> data;
vector<int> ans;
for(int i=0;i<k;++i){
data.push({nums[i],i});
}
ans.push_back(data.top().first);
for(int i=k;i<len;++i){
data.push({nums[i],i});
while(data.top().second <= i-k){
data.pop();
}
ans.push_back(data.top().first);
}
return ans;
}