239. Sliding Window Maximum (滑动窗口最大值, 大根堆or 单调队列)

 

You are given an array of integers 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 1:

Input: nums = [1,3,-1,-3,5,3,6,7], 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









方法一:优先队列(堆)

对于「最大值」,我们可以想到一种非常合适的数据结构,那就是优先队列(堆),其中的大根堆可以帮助我们实时维护一系列元素中的最大值。

import heapq
class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:

        q = [(-nums[i],i) for i in range(k)]
        n = len(nums)
        heapq.heapify(q)
        
        res = [-q[0][0]]
        for i in range(k,n):
            heapq.heappush(q,(-nums[i],i))
            while  q[0][1] <= i - k :
                heapq.heappop(q)
            res.append(-q[0][0])
        return res

 

 

 

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        n = len(nums)
        q = collections.deque()
        for i in range(k):
            while q and nums[i] >= nums[q[-1]]:
                q.pop()
            q.append(i)

        ans = [nums[q[0]]]
        for i in range(k, n):
            while q and nums[i] >= nums[q[-1]]:
                q.pop()
            q.append(i)
            while q[0] <= i - k:
                q.popleft()
            ans.append(nums[q[0]])
        
        return ans

 

 

 

 

 

 

 法1:

 1 class Solution {
 2 public:
 3     vector<int> maxSlidingWindow(vector<int>& nums, int k) {
 4         vector<int> res;
 5         priority_queue<pair<int, int>> q;
 6         for(int i = 0; i < k;++i) {
 7             q.push({nums[i],i});
 8         }
 9         res.push_back(q.top().first);
10 
11         for(int i = k;i < nums.size();++i) {
12             q.push({nums[i],i});
13             while(q.top().second + k <= i) {
14                 q.pop();
15             }
16             res.push_back(q.top().first);
17         }
18         return res;
19     }
20 };

 

 

法二:

 

https://labuladong.gitbook.io/algo/mu-lu-ye-1/mu-lu-ye-2/dan-tiao-dui-lie

 

首先,明确一个概念,单调队列是在队列中所有的元素都是单调的,要么单调增,要么单调减,新增元素时到队尾,此时队列不符合单调性就将队尾元素出队,直到队列单调或空。

 1 class MonotonicQueue {
 2 private:
 3     deque<int> data;
 4 public:
 5     void push(int n) {
 6         while (!data.empty() && data.back() < n) 
 7             data.pop_back();
 8         data.push_back(n);
 9     }
10     
11     int max() { return data.front(); }
12     
13     void pop(int n) {
14         if (!data.empty() && data.front() == n)
15             data.pop_front();
16     }
17 };
18 
19 class Solution {
20 public:
21     vector<int> maxSlidingWindow(vector<int>& nums, int k) {
22     MonotonicQueue window;
23     vector<int> res;
24     for (int i = 0; i < nums.size(); i++) {
25         if (i < k - 1) { //先填满窗口的前 k - 1
26             window.push(nums[i]);
27         } else { // 窗口向前滑动
28             window.push(nums[i]);
29             res.push_back(window.max());
30             window.pop(nums[i - k + 1]);
31         }
32     }
33     return res;
34     }
35 };

 

 1 class Solution {
 2 public:
 3     vector<int> maxSlidingWindow(vector<int>& nums, int k) {
 4     deque<int> q;
 5     vector<int> res;
 6     for (int i = 0; i < nums.size(); i++) {
 7         // push
 8         while(!q.empty()&& q.back() < nums[i]) {
 9             q.pop_back();
10         }
11         q.push_back(nums[i]);
12         if (i >= k - 1) { //前k - 1 已经填满
13             res.push_back(q.front());
14             // pop
15             if(!q.empty() && nums[i - k + 1]== q.front()) {
16                 q.pop_front();
17             }
18         }
19     }
20     return res;
21     }
22 };

 

posted @ 2021-05-23 17:39  乐乐章  阅读(73)  评论(0编辑  收藏  举报