[Leetcode] 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比队列中的第一个元素相等的时候,会保留相等元素,详细原因看参考代码中的注释。