LeetCode:https://leetcode.cn/problems/sliding-window-maximum/description/
一、一个故事
有一家互联网公司,它每个月都要招一名新的Java开发工程师。但是每一名工程师最多工作10个月就会被裁掉,无论他的工作能力多么好。
当这家公司招够了10个人之后,就开始对他们进行评估比较了,根据工程师的水平,选出这里面最好的一名,作为EOM(Employee of the Month),获得额外的薪水。之后的每个月,都有一位新人加入,一位老人固定被“优化”。
如果一个新人的能力比公司现在的老人能力还强,那在接下来的评比中,这些老人永远不会是Top1,他们的结局在这个新人进来的一刻就被注定了——他们既不可能作为EOM获得暂时的高工资,也难逃被裁的命运。所以每当有一名能力出众的新人入职,能力不如他的老人们都会集体辞职。
那么,每个月的EOM是谁呢?
这个问题,就是“滑动窗口最大值”,也称“谁是每月卷王?”。
二、关键点
请记住:
1、你注定被优化【不在窗口里了,就一定要移出队列】
2、如果一个人比你年轻还比你强,那你就失去了存在的意义【新来的比队列中的还大,那么队列中的就没有存在的必要了】
3、EOM,是干掉了他之前的所有人【最大的一定在队列的出口处】
三、实现代码
使用双端队列,实现单调队列
package StackAndQueue;
// 34 https://leetcode.cn/problems/sliding-window-maximum/description/
import java.util.Deque;
import java.util.LinkedList;
public class MaximumSlidingWindowValue {
public int[] maxSlidingWindow(int[] nums, int k) {
int[] result = new int[nums.length - k + 1];
int resultIndex = 0;
Deque<Integer> deque = new LinkedList<Integer>();
for (int i = 0; i < nums.length; i++) {
// 队首元素不在窗口内了,一定要把它移除
if (!deque.isEmpty() && i - deque.peekFirst() >= k) {
deque.removeFirst();
}
// 每进队一个元素,就把它前面的比他小的元素都移除
while (!deque.isEmpty() && nums[deque.peekLast()] < nums[i]) {
deque.removeLast();
}
deque.addLast(i);
if (!deque.isEmpty() && i >= k - 1) {
result[resultIndex++] = nums[deque.peekFirst()];
}
}
return result;
}
}