題目:給你一個整數數組?nums
,有一個大小為?k
?的滑動窗口從數組的最左側移動到數組的最右側。你只可以看到在滑動窗口內的?k
?個數字。滑動窗口每次只向右移動一位。
返回?滑動窗口中的最大值?。
分析:首先我們可以發現滑動窗口的移動操作和隊列的一進一出很相似,pop隊頭元素,push進隊尾一個元素。所以我們可以使用隊列來實現此題所需要的功能。但是題目要求返回滑動窗口的最大值,我們應該怎么做呢?大家一般第一想法就是對元素進行排序,但是排序之后我們還需要移動滑動窗口,即需要pop隊頭,那我們就無法pop正常需要pop的元素,每次pop的都是最大值,因此不能使用排序或者優先級隊列。我們可以自己設計需要的隊列讓它能夠找到最大值并且可以正確進行移動。
如何找到最大值,需要我們在push函數上進行設計。我們把最大值始終放在隊頭,把比它小的元素都pop掉。注意這里需要從back比較,并從back 進行pop,否則邏輯錯誤。
在pop函數設計時,由于我們有可能在push函數調用時已經pop了一些較小的元素,所以我們需要判斷要pop的元素是否和隊頭元素相等,若相等則pop,否則說明在在push函數調用時就已經pop了,那么就不需要執行任何操作。
具體代碼:
class Solution {
private:class Myqueue {public:deque<int> que;void pop(int value) {if(!que.empty() && value == que.front()) {que.pop_front();}}void push(int value) {while(!que.empty() && value > que.back()) {que.pop_back();}que.push_back(value);}int front() {return que.front();}};
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {Myqueue que;vector<int> result;for(int i = 0; i < k; i++) {que.push(nums[i]);}result.push_back(que.front());for(int i = k; i < nums.size(); i++) {que.pop(nums[i - k]);que.push(nums[i]);result.push_back(que.front());}return result;}
};