Leetcode 239. 滑動視窗最大值 (Java實現 超詳細註釋!)

Println30發表於2021-01-02

Leetcode 239. 滑動視窗最大值

涉及雙向佇列,說實話有點難理解啊!加了詳細的註釋,方便日後複習,也希望能幫到其他小夥伴,如有錯誤,歡迎指正!

Java實現:

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        int n = nums.length;
        // 由於滑動視窗本質就是每次刪除最前面的一個元素,新增一個元素再後面,因此這裡我們用雙向佇列儲存滑動視窗內的元素,方便增刪
        Deque<Integer> dq = new LinkedList<Integer>();
        // res用來儲存每次滑動視窗內的最大值
        int[] res = new int[n - k + 1];
        // 移動滑動視窗,其實就是從前往後移動,每一移動一位
        for (int i = 0; i < n; i++){
            // 由於我們需要找到滑動視窗內的最大值,我們可以採取這樣的方法:
            // 我們讓佇列頭部放最大值的索引(用索引是因為後面需要判斷是否要刪除已經越界的元素),佇列的尾部存較小且靠後的元素
            /**我們怎麼才能做到上述呢?
            頭部放最大的元素就是每次移動視窗時都從後往前比較新元素和老元素的大小,只要新元素更大就不斷地替換老元素,直到已經沒有老元素了
            怎麼保證佇列的尾部存較小且靠後的元素?我們可以在新元素小於最後一個老元素時,將新元素放在佇列的尾部;
            */
            while (!dq.isEmpty() && nums[dq.getLast()] <= nums[i]){
                dq.pollLast();
            }
            dq.offerLast(i);

            /**此時這次的視窗滑動已經結束了,我們要考慮是否有上一次的老元素越界的情況,因為是按順序儲存的,第一個元素一定是最靠前的元素;
            因此只有可能該元素越界,我們判斷該元素的索引是否等於i - k,等於說明越界,直接刪除*/
            if (dq.peekFirst() == i - k){
                dq.pollFirst();
            }
            // 到這一步我們需要獲取視窗內的最大值了,由於不滿三個元素時,不需要求最大值,從遍歷到第k個元素開始才需要求最大值
            if (i >= k - 1){
                // 由於最大的會一直往前挪,佇列頭部的元素此時一定是視窗內的元素,直接存入res中即可
                res[i - k + 1] = nums[dq.peekFirst()];
            }
        }
        return res;
    }
}

相關文章