トピック
整数の配列numsが与えられると、サイズkのスライディングウィンドウが配列の左端から右端に移動します。スライディングウィンドウにはk個の数字しか表示されません。スライディングウィンドウは、一度に1つの位置だけ右に移動します。
スライディングウィンドウの最大値を返します。
例1
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
--------------- -----
[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
単調キューソリューション
単調キュー
void push_front(n)//在队头插入n
void push_back(n)//在队尾插入n
void pop_front()//删除队首元素
void pop_back()//删除队尾元素
int front()
int back()
deque<int>window
添え字を格納する変数を宣言しました。この変数には、次の特性があります。
- 変数のフロントエンド(つまり、window.front())は、このトラバーサルの最大値の添え字です。
- 新しい番号に遭遇すると、新しい番号を2項目キューの最後(つまり、window.back())と比較します。最後が新しい番号よりも小さい場合、最後は最後まで破棄されます。キューが新しい数が多いか、キューが空の場合にのみ停止します。アプローチは、スタックを使用して括弧を一致させるのと少し似ています。
- deque内のすべての値はウィンドウ範囲内にある必要があります
最初の機能は、各ウィンドウが1グリッドスライドした後に最大値を取得するのが便利なことです。これは、window.front()から直接取得できます。
機能2により、キュー内の要素が最初から最後まで降順であることが保証されます。キュー内のウィンドウには数字しかないため、実際には、それらは1番目、2番目、3番目...の数字です。窓。
特徴3は質問の意味に応じて設定されています。しかし、実際には現在の添え字をwindow.front()と比較するだけです。理由を考えてみてください。
回答:ウィンドウの最初の要素がウィンドウのwindow.front()である限り、2番目と3番目の要素が範囲内にあるかどうかは関係ありません。答えは一番の要素でなければならないからです。window.front()がウィンドウにない場合は、ポップアップされ、2番目に大きい要素が最初に大きい要素になり、3番目に大きい要素が2番目に大きい要素になります。
コードを記述するプロセスでは、例外がスローされないように、キューが空かどうかを常に確認する必要があります。
時間の複雑さ
コード
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
int n=nums.size();
deque<int>q;
for(int i=0;i<k;++i)//i表示滑动窗口的最右侧下标
{
while(!q.empty()&&nums[i]>nums[q.back()])
q.pop_back();
q.push_back(i);
}
vector<int>result;
for(int i=k;i<n;++i)//i表示滑动窗口的最右侧下标
{
while(!q.empty()&&nums[i]>nums[q.back()])
q.pop_back();
q.push_back(i);
if(q.front()<=i-k)
q.pop_front();
result.push_back(nums[q.front()]);
}
}