(Java算法)劍指offer-面試題59 - I. 滑動窗口的最大值

給定一個數組 nums 和滑動窗口的大小 k,請找出所有滑動窗口裏的最大值。
 
示例:

輸入: 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
 

提示:

你可以假設 k 總是有效的,在輸入數組不爲空的情況下,1 ≤ k ≤ 輸入數組的大小。

本題採用雙端隊列的方法來完成,首先先介紹一下雙端隊列,Deque。這是一個接口,我們一般在使用的時候,都使用ArrayDeque,LinkedList,也就是說,一個是基於數組,一個是基於鏈表。他和普通的隊列最大的區別就在於,雙端隊列從兩端都可以進行隊列的操作。

解題步驟:本題的目的是用長度爲k的數組進行入隊出隊的操作,直到滑到最右邊,然後將每次滑動產生的新數組內的最大值,存儲到一個新的數組中,最後返回這個數組。

解題思路:我們可以將這個滑動的數組,翻譯成一個雙端隊列。將每次將來進隊的數字和隊列最右邊(隊尾)進行比較,如果新數字大,就將隊尾進行出隊操作,新數進行入隊操作。那麼問題就來了,我們要如何知道新進來的數字,成爲雙向隊列對頭的時機呢,也可以說,我們如何讓窗口和雙向隊列裏面的數保持一致呢?這就可以用一個技巧。我們可以用隊列不去存儲value,而去存儲在nums裏面的下標,然後就可以判斷這個數實際的下標了。

public int[] maxSlidingWindow(int[] nums, int k) {
        Deque<Integer> deque = new ArrayDeque<>();
        if(nums.length==0){
            return new int[0];
        }
        int arr[] = new int[nums.length-k+1];
        for(int i = 0 ; i<nums.length ; i++){
            if(!deque.isEmpty()&&deque.peekFirst()==i-k){
                deque.removeFirst();
            }
            while(!deque.isEmpty()&&nums[deque.peekLast()]<nums[i]){
                deque.removeLast();
            }
            deque.offerLast(i);
            if(i>=k-1){
                arr[i-k+1]=nums[deque.peek()];
            }
        }
        return arr;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章