雙端隊列題解

雙端隊列題解

239. 滑動窗口最大值

牛客鏈接
LeetCode 鏈接

方法一:暴力法

該題最直接的解法,直接遍歷每個滑動窗口,找到每個窗口的最大值即可。一共會有 N - k + 1 個滑動窗口,每個滑動窗口有 k 個元素,所以時間複雜度爲 O(Nk),表現較差。

方法二:雙端隊列

這裏採用 以雙向鏈表實現的 LinkedList 作爲雙端隊列。
算法

  • 遍歷整個數組。
  • 把當前元素的索引添加到雙端隊列中,在添加之前首先清理雙端隊列:
    • 遍歷當前雙端隊列。
    • 移除比當前元素小的所有元素,它們不可能是最大的,保證雙端隊列隊首到隊尾按從大到小的順序排列,這樣保證了隊首永遠是當前窗口最大的。
  • 如果隊首的索引超出了窗口,則移除對首。
  • 將對首元素添加到輸出數組中。
    public int[] maxSlidingWindow(int[] nums, int k) {
        if(nums == null || nums.length == 0) return new int[0];
        LinkedList<Integer> qmax = new LinkedList<>();
        int[] result = new int[nums.length - k + 1];
        int index = 0;
        for(int i = 0; i < nums.length; i++) {
		    // 遍歷雙端隊列,將比當前元素小的所有元素移除
            while(!qmax.isEmpty() && nums[i] >= nums[qmax.peekLast()]) {
                qmax.pollLast();
            }
			// 將當前元素的索引添加到隊列
            qmax.addLast(i);
			// 如果隊首的索引超出了窗口,移除
            if(qmax.peekFirst() == i - k) {
                qmax.pollFirst();
            }
			// 第一個窗口生成,構建輸出結果
            if(i >= k - 1) {
                result[index++] = nums[qmax.peekFirst()];
            }
        }
        return result;
    }

複雜度

  • 時間複雜度:O(N),每個元素被處理兩次,其索引被添加到雙端隊列,和被雙端隊列刪除。
  • 空間複雜度:O(N),輸出數組使用了 O(N - k + 1) ,雙端隊列使用了 O(k)。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章