滑动窗口最大值
思路
想到使用队列或双指针方便进行滑动窗口操作。然后设置纪录最大值变量,遍历判断窗口内最大值。
结果暴力超时!
问题在于如何在最大值出队时,立即找到第二大的值。
题解,使用双端队列,且队列保留最大值,新入队的元素,删除队列内小于新入队元素的值。同时保持队列递减。
总结
重点在于找队列中最大值,及控制每个元素的出队情况。队列中的size不一定要等于滑动窗口大小。只需保留最大值在队首,以及其后小于其的值。如此队列就是递减队列。其中一个重要的点是判断队列最大值的出队时间,如果size等于滑动窗口大小,则可判断。当size小于滑动窗口大小时,需要判断nums[i-k]的值是否为队首的最大值,代表k个循环前入队,可以出队了。
这道题主要在于找队列的最大值,使用单调及双端队列来解答。可参考https://blog.csdn.net/m0_49499183/article/details/123660448
代码
public static int[] maxSlidingWindow(int[] nums, int k) {
Deque<Integer> dueue=new ArrayDeque<>();
int[] result = new int[nums.length-k+1];
int i=0;
while (i<k){
if (i==0 || !dueue.isEmpty() && dueue.peekLast()>nums[i]) dueue.offer(nums[i]);
else {
while (!dueue.isEmpty() && dueue.peekLast()<nums[i]) dueue.pollLast();
dueue.offerLast(nums[i]);
}
i++;
}
int s=0;
result[s++]=dueue.peekFirst();
for (;i< nums.length;i++){
if (dueue.peekFirst()==nums[i-k]) dueue.pollFirst(); //判断最大值什么时候出队
if (!dueue.isEmpty() && dueue.peekLast()>nums[i]) dueue.offer(nums[i]); //将最小值放在队尾
else { //除去比新入队元素小的元素
while (!dueue.isEmpty() && dueue.peekLast()<nums[i] ) dueue.pollLast();
dueue.offerLast(nums[i]);
}
result[s++]=dueue.peekFirst();
}
return result;
}