这道题的题目比较简单,就是在数组中滑动窗口,并找出每次滑动之后窗口中的最大值输出,题目如下所示:
在上一篇博文数据流中的第K大元素中提到了优先队列,我们可以尝试用优先队列来解答这个问题,首先移动窗口的时候,我们需要把窗口最左边的元素剔除掉,然后将新进入的元素加入到优先队列中,然后再在大顶堆中整理元素位置,代码如下:
class Solution { public int[] maxSlidingWindow(int[] nums, int k) { int numLen = nums.length; if(nums == null || numLen<k || k<=0){ return nums; } int[] res = new int[numLen-k+1]; PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>((a,b)->nums[b]-nums[a]); for(int i=0;i<k-1;i++){ maxHeap.offer(i); } for(int i=k-1;i<numLen;i++){ maxHeap.offer(i); while(maxHeap.peek()<i-(k-1)){ maxHeap.poll(); } res[i-(k-1)] = nums[maxHeap.peek()]; } return res; } }
这个时候的时间复杂度为:
,我们可以用双向队列来求解此问题更加简化了时间复杂度,整个过程如下图所示:
假设有一个数组
,
,我们用双端队列,每一轮进行移动窗口、维护和输出的动作,每一轮使最大的数在窗口的最左端,如果窗口中左边的元素要小于右边的元素,那么就把左边的元素进行清除维护,最终就能输出结果,图中红色的部分表示窗口的位置。代码如下:
class Solution(object): def maxSlidingWindow(self, nums, k): """ :type nums: List[int] :type k: int :rtype: List[int] """ if not nums: return [] window, res = [], [] for i, x in enumerate(nums): if i >= k and window[0] <= i - k: window.pop(0) while window and nums[window[-1]] <= x: window.pop() window.append(i) if i >= k-1: res.append(nums[window[0]]) return res
这个时候整个算法的时间复杂度就为: ,比上面用优先队列的方法时间复杂度要低很多。这就是滑动窗口中用优先队列和双向队列的解法,希望对大家有所帮助,谢谢。