题目:
题解:
解法1:
- 暴力法+滑动窗口。
- left、right分别表示窗口的左右边界,当窗口的大小为k(
right-left+1=k
)时,用max_element()
求出窗口内的最大值添加到result即可,然后遍历数组,直到right=nums.size()
时遍历结束,返回result。
解法2:
- 双向队列+滑动窗口。
- duque用来存放窗口window的下标,并保持窗口头部的下标表示的元素为该窗口的最大值。当添加新元素时,新元素与
窗口尾部下标表示的元素window.back()
相比较,若新元素大于窗口尾部下标表示的元素window.back()
,则直接把尾部下标弹出队列window.pop_back()
直至新元素小于尾部下标表示的元素window.back()
或窗口为空为止。还有一点需要注意的是:当窗口头部的下标小于等于i-k时,需要将头部下标弹出队列window.pop_front()
,因为此时窗口中的队头下标属于上一个窗口的,需要删除。
代码如下:
class Solution {
public:
//解法1:暴力法+滑动窗口
vector<int> maxSlidingWindow_1(vector<int>& nums, int k) {
vector<int> result;
int left=0,right=0,n=nums.size();
while(right<n)
{
if(right-left+1==k)//达到窗口k
{
auto it=max_element(nums.begin()+left,nums.begin()+right+1);//求出窗口的最大值
result.push_back(*it);
left++;
}
right++;
}
return result;
}
//解法2:双向队列+滑动窗口
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
if(nums.empty()||k==0)return {};
vector<int> result;
deque<int> window;//窗口,窗口保存数组的下标
for(int i=0;i<k;++i)
{
//窗口不为空并且下标i表示的元素大于window尾部下标表示的元素,删除尾部下标,保证窗口的头部为最大值
while(!window.empty()&&nums[i]>nums[window.back()])
window.pop_back();
window.push_back(i);//此时窗口的头部为最大值
}
//将第一个窗口的最大值添加到result中
result.push_back(nums[window.front()]);
for(int i=k;i<nums.size();++i)
{
//窗口中的队头下标小于等于i-k表示队头下标属于上一个窗口的,需要删除
if(!window.empty()&&window.front()<=i-k)
window.pop_front();
//窗口不为空并且下标i表示的元素大于window尾部下标表示的元素,删除尾部下标,保证窗口的头部为最大值
while(!window.empty()&&nums[i]>nums[window.back()])
window.pop_back();
window.push_back(i);//此时窗口的头部为最大值
result.push_back(nums[window.front()]);//将窗口的最大值添加到result中
}
return result;
}
};