タイトル説明:
整数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
例2:
入力:nums = [1]、k = 1
出力:[1]
例3:
入力:nums = [1、-1]、k = 1
出力:[1、-1]
例4:
入力:nums = [9,11]、k = 2
出力:[11]
例5:
入力:nums = [4、-2]、k = 2
出力:[4]
制約:
1 <= nums.length <= 10 5
-10 4 <= nums [i] <= 10 4
1 <= k <= nums.length
時間計算量:O(n)
空間計算量:O(k)
スライディングウィンドウを移動するときに、現在のスライディングウィンドウに2つの添え字iとjがある場合、iはjの左側にあり(i <j)、 iに対応する要素は、j nums [i] <= nums [j]に対応する要素より大きくありません。スライディングウィンドウが右に移動するとき、iがウィンドウ内にある限り、jもウィンドウ内にある必要があります。 i injであるウィンドウは左側で保証されています。したがって、nums [i] <= nums [j]。が存在するため、nums [i]はスライディングウィンドウの最大値であってはならず、nums [i]を完全に削除できます。
- Dequeを使用して、削除されていないすべての添え字を保存します。キューでは、これらの添え字は昇順で配置され、配列nums内の対応する値は厳密に単調に減少しています。上記の分析によれば、iがjの左側にある場合(i <j)、対応する要素nums [i] <= nums [j]の場合、iは削除されます。
- スライディングウィンドウが右に移動すると、新しい要素がキューに追加されます。キューの単調な減少性を維持するために、新しい要素は常にキューの最後の要素と比較されます。新しい要素が大きい場合、キューの最後の要素はキューから排出されます。この操作は、キューが空になるか、新しい要素がキューの最後の要素よりも小さくなるまで続けられます。
- このとき、チーム長の添え字に対応する要素がスライディングウィンドウの最大値になります。ウィンドウが右に移動すると、スライディングウィンドウのサイズが境界を越えます。ラインの先頭にある要素がウィンドウに表示されるまで、要素をラインの先頭から連続的にポップする必要があります。
キューの最初と最後の要素を同時にポップするには、両端キューを使用する必要があります。この単調性を満たす両端キューは、一般に「単調キュー」と呼ばれます。
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums == null || nums.length < 2) return nums;
int n = nums.length;
int[] res = new int[n-k+1];
Deque<Integer> queue = new ArrayDeque<>();
for(int i = 0; i < n;i++){
while(!queue.isEmpty() && nums[queue.peekLast()] < nums[i]){
queue.pollLast();
}
queue.addLast(i);
if(queue.peekFirst() <= i-k){
queue.poll();
}
if(i >= k-1){
res[i-k+1] = nums[queue.peek()];
}
}
return res;
}
}