239. Sliding Window Maximum
problem description
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
Note:
You may assume k is always valid, 1 ≤ k ≤ input array's size for non-empty array.
Follow up: Could you solve it in linear time?
algorithm thought
经典的滑动窗口问题。如果最暴力的方法就是每移动一步,循环判断所有的数字,找到最大值。但是这样做的话,时间复杂度就是O(nk),还是需要挺久时间的。
由于前一次查找到的最大值过程中,很多信息对后一次来说肯定也是能用上的。所以需要想个办法利用之前的信息。
首先需要知道的一点是,如果当前来了个很大的值,那么还在窗口中的,之前的比这个值小的值就已经失去作用了。之后肯定不会被放入结果。那么我们就在每次加入新数的时候,将之前比它小的数剔除,然后将当前值插入。这样就能保证当前最后一个数就是最大值了。还需要注意的一个点是,当窗口中的数大于k的时候,需要剔除最后一个数。
现在,另一个重要的问题就是,根据上面提出的需求,选取合适的数据结构来解题。在上面的需求中,我们既要操作尾端(剔除最后一个数),也要操作首端(加入新数的时候,剔除比他小的数)。这两个操作都是线性时间的数据结构有链表和双端队列。这里我们用双端队列实现
code
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> ans;
deque<int> q;
for(int i=0;i<nums.size();++i){
if(!q.empty() && i-q.front()>=k)
q.pop_front();
while(!q.empty() && nums[q.back()]<=nums[i])
q.pop_back();
q.push_back(i);
if(i>=k-1)
ans.push_back(nums[q.front()]);
}
return ans;
}
};
algorithm analysis
这里需要用平均情况去分析。对于每一个数,都只进行了一个入队和出队操作,所以,平均时间复杂度是O(n)
Last updated