題目:給定一個數組和滑動窗口的大小,找出全部滑動窗口裏數值的最大值。例如,若是輸入數組{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]}。java
思路:算法
若是用暴力搜索算法,毫無疑問,時間複雜度爲O(nk)。咱們能夠開闢一個雙端隊列來存儲有可能成爲滑動窗口最大值的數的下標,使當前滑動窗口的最大值爲隊列的第一個元素,每次從數組中取出一個元素與隊列中尾端元素進行比較,前者大於後者則移除後者,往隊列尾端加入前者,前者小於後者就直接加入隊列尾端。數組
以數組{2,3,4,2,6,2,5,1}爲例講解。數組第一個數是2,存入隊列,第二個數是3,3大於2,把2移除,存入3,第三個數是4,4大於3,把3移除,存入4,此時隊列的元素爲{4};spa
第四個數是2,2小於4,當4滑出滑動窗口以後,2有可能成爲最大值,把2存入隊列尾部,此時隊列元素爲{4,2};code
第五個數是6,6大於隊列中的2和4,所以2和4已經不可能成爲滑動窗口中的最大值,從隊列中移除2和4;blog
第六個數是2,2小於6,存入隊列,此時隊列元素爲{6,2};隊列
第七個元素是5,5與隊列的尾端比較,5大於2,移除2,5小於6,把5存入隊列尾端,此時隊列元素爲{6,5};rem
最後一個元素是1,1小於5,入隊列,但此時6已經不在滑動窗口中了,移除6,隊列中元素爲{5,1}。get
如何判斷一個數是否在滑動窗口中呢?io
這就是爲何把數字在數組中的下標存到數組而不是把數字存到數組的緣由,當一個數字的下標與當前處理的數字的下標之差大於或等於滑動窗口的大小時,這個數字已經從滑動窗口中滑出,能夠從隊列中移除了。
這種算法的時間複雜度爲O(n)。
參考代碼:
import java.util.ArrayList; import java.util.LinkedList; public class Solution { public ArrayList<Integer> maxInWindows(int [] num, int size) { ArrayList<Integer> result = new ArrayList<Integer>(); if(num == null || num.length == 0 || size == 0)return result; LinkedList<Integer> queue = new LinkedList<Integer>();
//初始化 for(int i=0;i<size-1;i++){ while(!queue.isEmpty() && num[i] > num[queue.getLast()]){ queue.removeLast(); } queue.addLast(i); } for(int i=size-1;i<num.length;i++){ while(!queue.isEmpty() && num[i] > num[queue.getLast()]){ queue.removeLast(); } queue.addLast(i);
//數字是否在滑動窗口中 if (i-queue.getFirst()+1 > size) queue.removeFirst(); result.add(num[queue.getFirst()]); } return result; } }