这道题的题目比较简单,就是在数组中滑动窗口,并找出每次滑动之后窗口中的最大值输出,题目如下所示:
在上一篇博文数据流中的第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
这个时候整个算法的时间复杂度就为:,比上面用优先队列的方法时间复杂度要低很多。这就是滑动窗口中用优先队列和双向队列的解法,希望对大家有所帮助,谢谢。