劍指64.滑動視窗的最大值
阿新 • • 發佈:2020-09-11
題目描述
給定一個數組和滑動視窗的大小,找出所有滑動窗口裡數值的最大值。例如,如果輸入陣列{2,3,4,2,6,2,5,1}及滑動視窗的大小3,那麼一共存在6個滑動視窗,他們的最大值分別為{4,4,6,6,6,5}; 針對陣列{2,3,4,2,6,2,5,1}的滑動視窗有以下6個: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。 視窗大於陣列長度的時候,返回空思路
一個滑動視窗可以看成一個佇列,當視窗滑動時,處於視窗的第一個數字被刪除,同時在視窗的末尾新增一個新的數字,這符合佇列“先進先出”。
思路1:暴力法。時間複雜度為O(nk)
思路2:增減維護一個優先佇列。時間複雜度O(n logk)
思路3:通過單調Deque雙端佇列。Deque裡頭最大,尾最小。注意Deque裡存的是index,不是值。 (時間複雜度O(n),每個下標最多進一次,出一次。)
步驟:頭尾尾頭
- 1)頭部出隊
- 2)尾部清理
- 3)尾部入隊
- 4)返回頭部
☆☆☆☆解法
import java.util.ArrayList; import java.util.Deque; import java.util.LinkedList; public class Solution {public ArrayList<Integer> maxInWindows(int [] num, int size) { ArrayList<Integer> list = new ArrayList<>(); if (num == null || size < 1 || num.length < size) return list; // 雙端佇列,deque裡存的是陣列的index,不是陣列的值 Deque<Integer> deque = newLinkedList<>(); for (int i = 0; i < num.length; i++) { //Step1: 頭: 移除頭部, 保證視窗的長度範圍 if (!deque.isEmpty() && (i - deque.getFirst()) >= size){ //這個條件也可以換成 deque.getFirst() < (i - (size - 1)) deque.removeFirst(); } //Step2: 尾: 移除尾部小於當前值的元素, 去除不可能的元素 while (!deque.isEmpty() && num[i] >= num[deque.getLast()]){ deque.removeLast(); } //Step3: 尾部加入, 滑動視窗向右擴充 deque.addLast(i); //Step4: 頭, 從頭部返回極大值 if (i >= size - 1){ list.add(num[deque.getFirst()]); //list.add(num[deque.peekFirst()]); //所有的dq.getFirst()也可以換為dq.peekFirst() } } return list; } }
參考: