給你一個整數數組?nums
,有一個大小為?k
?的滑動窗口從數組的最左側移動到數組的最右側。你只可以看到在滑動窗口內的?k
?個數字。滑動窗口每次只向右移動一位。
返回?滑動窗口中的最大值?。
示例 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 31 [3 -1 -3] 5 3 6 7 31 3 [-1 -3 5] 3 6 7 51 3 -1 [-3 5 3] 6 7 51 3 -1 -3 [5 3 6] 7 61 3 -1 -3 5 [3 6 7] 7
示例 2:
輸入:nums = [1], k = 1 輸出:[1]
提示:
1 <= nums.length <= 105
-104?<= nums[i] <= 104
1 <= k <= nums.length
對于這道題目來說,最應該相到也是我覺得最容易看懂的就是雙向隊列來實現,首先要明確用隊列來做的話,要想清楚一個思路,因為java沒有函數可以直接實現查找k個數得最大值,所以要放入隊列里面的話就必須吧其中最大的值放在顯眼位置就例如隊首或者隊尾,既然這樣如果把最大值放入隊首了,那就和單調隊列一個思路,如果后面插入的值小于隊首就進入隊列放在后面,如果進來的值大于隊首,就取代他放到隊首,此時從什么時候開始取最大值呢?就是當i>=k-1的時候,這里還有一個容易錯的地方就是,此時還要判斷隊首的值什么時候出隊列,因為這是一個滑動窗口,不可能你一開始的最大值在移動了幾個后還在隊列當中,所以此時還要判斷當i<i-k+1的時候還要將隊首元素pop出去,代碼如下
class Solution {public int[] maxSlidingWindow(int[] nums, int k) {ArrayDeque<Integer> deque = new ArrayDeque<>();int n = nums.length;int[] res = new int[n - k + 1];int idx = 0;for(int i = 0; i < n; i++) {// 1.隊列頭結點需要在[i - k + 1, i]范圍內,不符合則要彈出while(!deque.isEmpty() && deque.peek() < i - k + 1){deque.poll();}// 2.既然是單調,就要保證每次放進去的數字要比末尾的都大,否則也彈出while(!deque.isEmpty() && nums[deque.peekLast()] < nums[i]) {deque.pollLast();}deque.offer(i);// 因為單調,當i增長到符合第一個k范圍的時候,每滑動一步都將隊列頭節點放入結果就行了if(i >= k - 1){res[idx++] = nums[deque.peek()];}}return res;}
}