1 题目
Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Return the max sliding window.
Example:
Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3
Output: [3,3,5,5,6,7]
Explanation:
Window position Max
--------------- -----
[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 尝试解
2.1 分析
给定一个数组A,以及一个大小为K的滑窗,求所有滑窗内最大值组成的数组。
可以滑动滑窗,每次取其中的最大值,这样复杂度为O(KN)。考虑使用一个堆,存储每个元素的值及索引。每次滑窗向右移动一步,弹出堆顶元素,如果超出滑窗范围,继续弹出,直到找到滑窗范围内的最大元素,这样复杂度为O(NlgN),因为过期元素可能因为值过小处于堆底而无法删除。
考虑一个链表saver用来存储当前滑窗内的元素索引,元素依照顺序加入其中。当滑窗移动到位置i时
if(i-saver.front() >= k) i.pop_front() 即删除过期元素
while(A[saver.back()] < A[i]) saver.pop_back() 即如果元素i比前一个被存储的元素back要大,那么只要i和back同时在滑窗内,最大元素就不可能是back,所以当i加入滑窗时,可以删去back,更新back,直到back比i大或者saver为空。这就决定了saver是单调递减的,最大元素就是saver.front()。
2.2 代码
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
list<int> saver;
vector<int> result;
for(int i = 0; i < nums.size();i++){
if(!saver.empty()){
if(i-saver.front()>=k){
saver.pop_front();
}
while(saver.size() && nums[i]>nums[saver.back()]){
saver.pop_back();
}
}
saver.push_back(i);
if(i >= k-1)
result.push_back(nums[saver.front()]);
}
return result;
}
};
3 标准解
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> dq;
vector<int> ans;
for (int i=0; i<nums.size(); i++) {
if (!dq.empty() && dq.front() == i-k) dq.pop_front();
while (!dq.empty() && nums[dq.back()] < nums[i])
dq.pop_back();
dq.push_back(i);
if (i>=k-1) ans.push_back(nums[dq.front()]);
}
return ans;
}
};