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.
For example,
Given nums = [1,3,-1,-3,5,3,6,7]
, and k = 3.
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
Therefore, return the max sliding window as [3,3,5,5,6,7]
.
Note:
You may assume k is always valid, ie: 1 ≤ k ≤ input array's size for non-empty array.
Follow up:
Could you solve it in linear time?
Hint:
- How about using a data structure such as deque (double-ended queue)?
- The queue size need not be the same as the window’s size.
- Remove redundant elements and the queue should store only elements that need to be considered.
这道题是找滑动窗口中的最大值,题目难度为Hard。
提示已经基本说出了解题思路,假设滑动窗口移动到了第m个数字,那它之前的数字哪些是需要记录下来以备后续比较使用的呢?第m-k+1个数字之前的数字不在窗口内,所以是不用考虑的,而在第m-k+1到第m个数字之间的k个数中,哪些又是不必考虑的呢?窗口移动到第m个数字时,和第m个数字左相邻的数字如果比第m个数字小,那它在移出窗口之前会一直和第m个数字同时在窗口中,所以它是不需要考虑的,也就没必要存储了,这样一直向左直至找到比第m个数字大的数字(假定为第n个数字),第n到第m之间的数字都是不需要考虑的,最终存储下来的数字会呈现出递减的趋势,也就是说存储的第一个数字即是窗口中最大的数字。如果马上移出窗口的数字等于存储的最大数字(相等数字也照顾到了),说明当前窗口中最大的数字在窗口最左端,马上要移出窗口,所以需要删除存储的第一个数字。既然在首部和尾部都需要删除数据,所以我们选择双端队列来存储数据。依照上面介绍的方法顺序遍历数组,在遍历到第k个数字之后每次遍历时将队列首部的数据存入最终结果即可。具体代码:
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> window;
vector<int> ret;
for(int i=0; i<nums.size(); ++i) {
while(!window.empty() && window.back() < nums[i]) {
window.pop_back();
}
window.push_back(nums[i]);
if(i >= k-1) {
if(i != k-1 && nums[i-k] == window.front()) window.pop_front();
ret.push_back(window.front());
}
}
return ret;
}
};