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]
.
Note:
You may assume k is always valid, ie: 1 ≤ k ≤ input array's size for non-empty array.
Follow up:
Could you solve it in linear time?
这道题理解了sliding window的本质还是挺好做的,每次减一个再加一个保证priorityqueue里面只有k个值就可以了。
注意:
Java默认为最小堆,不要忘记改为最大的。另外要注意单独处理最后一个值。
public class Solution { public int[] maxSlidingWindow(int[] nums, int k) { if (nums.length == 0) { return new int[0]; } int[] res = new int[nums.length - k + 1]; PriorityQueue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder()); for (int i = 0; i < k; i++) { pq.add(nums[i]); } for (int i = k; i < nums.length; i++) { res[i - k] = pq.peek(); pq.remove(nums[i - k]); pq.add(nums[i]); } res[nums.length - k] = pq.peek(); return res; } }
follow up要求O(n),虽然听过但还是用普通的queue做了一遍才知道queue为啥不行。。。用deque的主要思路是每次移走k范围外的数,剩下的数按照从大到小排列。添加一个数的时候,如果queue里面的数比要添加的数小,就移出来。这样每次保证头部的就是结果。
public class Solution { public int[] maxSlidingWindow(int[] nums, int k) { if (nums.length == 0) { return new int[0]; } int[] res = new int[nums.length - k + 1]; Deque<Integer> dq = new LinkedList<>(); for (int i = 0; i < nums.length; i++) { while (!dq.isEmpty() && dq.peek() <= i - k) { dq.poll(); } while (!dq.isEmpty() && nums[dq.peekLast()] <= nums[i]) { dq.pollLast(); } dq.offer(i); if (i - k + 1 >= 0) { res[i - k + 1] = nums[dq.peek()]; } } return res; } }
另外发现ArrayDeque比linkedlist快。到时候回顾下这个题目好了。