题目:
大根堆思路:
维护最大值,应该首先想到大根堆。C++中对应着priority_queue,这里用pair<int,int>来记录对应的值和在nums中的索引。所以有priority_queue<pair<int,int>> q。在大根堆中,用q.top().first即可获取最大值。对于滑动窗口有三个步骤:处理进入的元素、处理出去的元素、记录结果。直接看代码吧,很清晰的。
大根堆代码
C++代码
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
//大根堆
priority_queue<pair<int,int>> q;
//初始化大根堆
for(int i=0;i<k;i++){
q.emplace(nums[i],i);
}
//初始化res
vector<int> res={q.top().first};
//处理后续窗口
int len=nums.size();
for(int i=k;i<len;i++){
//进入
q.emplace(nums[i],i);
//出去
while(q.top().second<=i-k){
q.pop();
}
//记录答案
res.push_back(q.top().first);
}
return res;
}
};
对于priority_queue,增添元素为emplace,删除元素为pop。
定义小根堆的话(C++默认大根堆),需要把代码:
priority_queue<pair<int,int>> q;
转换为:(或者直接对元素取负就行)
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
python代码:
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
q=[]
for i in range(k):
heapq.heappush(q,(-nums[i],i))
res=[-q[0][0]]
len_nums=len(nums)
for i in range(k,len_nums):
heapq.heappush(q,(-nums[i],i))
while q[0][1]<=i-k:
heapq.heappop(q)
res.append(-q[0][0])
return res
注意,python中默认的是小根堆 ,需要导入包import heapq
对于加入元素操作:
heapq=[]
heapq.heappush(q,(-nums[i],i))
删除元素操作:
heapq.heappop(q)
双端队列思想:
- 滑动窗口加入元素
每当从末端加入一个元素时,都要跟双端队列的末尾元素进行比较,如果末尾的元素更小,当加入该元素后,末尾元素一定不是最大值,所以在加入该元素之前,将末尾元素pop掉(这里运用while循环)。滑动窗口移出元素
加入该元素后,还要判断双端队列最开始的元素的索引是否在要求的滑动窗口中,如果不在,那需要把最前面的元素pop掉(while循环)。
记录答案
可以考虑到这是一个递减的双端队列,所以最大值永远是第一个元素。
双端队列代码:
C++代码:
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
int len=nums.size();
//只记录数组索引的双端队列
deque<int> q;
//初始化双端队列
for(int i=0;i<k;i++){
while(!q.empty() && nums[q.back()]<=nums[i]){
q.pop_back();
}
q.push_back(i);
}
//初始化答案
vector<int> res={nums[q.front()]};
//滑动窗口---进入/移出/记录答案
for(int i=k;i<len;i++){
//进入
while(!q.empty() && nums[q.back()]<=nums[i]){
q.pop_back();
}
q.push_back(i);
//移出
while(q.front()<=i-k){
q.pop_front();
}
//记录答案
res.push_back(nums[q.front()]);
}
return res;
}
};
python代码:
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
len_nums=len(nums)
q=deque()
for i in range(k):
while q and nums[q[-1]]<=nums[i]:
q.pop()
q.append(i)
res=[nums[q[0]]]
for i in range(k,len_nums):
while q and nums[q[-1]]<=nums[i]:
q.pop()
q.append(i)
while q[0]<=i-k:
q.popleft()
res.append(nums[q[0]])
return res
注意需要引入头文件from collections import deque
q=deque()
C++:q.back()
python:q[-1]
#双端队列deque插入/删除元素
q.append(i)
q.pop()
q.popleft()