標籤:
Sliding Window Maximum
Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position.
For example,
Given nums = [1,3,-1,-3,5,3,6,7], and k = 3.
Window position Max--------------- -----[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
Therefore, return the max sliding window as [3,3,5,5,6,7].
剛開始想到是使用heap來儲存當前遍曆過的元素,並且保持最大堆狀態,每當達到從堆中取出一個元素,則將當前節點之前的第k個元素從堆中刪除,這樣堆一直保持k的大小,整體演算法的複雜度是O(N*k(logk)),從堆中刪除需要找到需要找到節點,時間是O(K),刪除O(Log(k)),最多N個節點。
1 private int[] method2(int []nums,int k){ 2 if(nums.length==0) return nums; 3 Comparator<Integer> compare = new Comparator<Integer>(){ 4 public int compare(Integer i1,Integer i2){ 5 return i2-i1; 6 } 7 }; 8 PriorityQueue<Integer> heap = new PriorityQueue<Integer>(compare); 9 int [] res = new int[nums.length-k+1];10 for(int i=0;i<nums.length;i++){11 heap.offer(nums[i]);12 if(i>=(k-1)){13 res[i-k+1] = heap.peek();14 heap.remove(nums[i-k+1]);15 }16 }17 return res;18 }19 public int[] maxSlidingWindow(int[] nums, int k) {20 return method2(nums,k);21 }
後來發現使用雙端隊列,就可以,並且時間複雜度降低到了O(N)
1 private int[] method1(int[] nums, int k){ 2 if(nums.length==0) return nums; 3 LinkedList<Integer> dequeue = new LinkedList<Integer>(); 4 int [] res = new int[nums.length-k+1]; 5 for(int i=0;i<nums.length;i++){ 6 int data = nums[i]; 7 //當data等於雙端隊列當中的最大值的時候,不能講隊列中的元素彈出, 8 //原因是這個元素可能會被後面的某個元素視為最大元素,當前遇到的這個值雖然和雙端隊列當中目前的最大值是相等的,但是他出現的比較晚,在後面的視窗當中他可能會被用到。 9 //舉個例子 4444333,如果遇到想的就刪除,那麼10 //4 4 4 4 變為空白,遇到3的時候雖然視窗大小為3的視窗中的最大值是4,但是4已經不存在了,關鍵是在前面已經把他刪除了。11 12 while(dequeue.size()!=0&&data>dequeue.getFirst()) dequeue.removeFirst();13 dequeue.addFirst(data);14 if(i>=k-1){15 int largest = dequeue.getLast();16 res[i-k+1] = largest;17 if(largest==nums[i-k+1]){18 dequeue.removeLast();19 }20 }21 }22 return res;23 }
這裡的關鍵問題是while迴圈當中為甚me在當前data比隊列中的第一個元素相等的時候,會保留相等元素,詳細原因看參考代碼中的注釋。
[Leetcode] Sliding Window Maximum