先使用双向链表构建一个单调递减队列,有三个方法:
- push 在队尾添加元素,但要将前面比它小的元素删除。
- max 返回最大元素,即队头
- pop 若元素为队头,则删除(判断是因为有可能被压扁了,已经不存在了)
然后,遍历数组,先把队列前 k - 1 个填满,再开始向前滑动移入新元素,再记录最大值,再移出旧元素。
public class Solution {
class MonotonicQueue {
// 双链表,支持头部和尾部增删元素
LinkedList<Integer> q = new LinkedList();
public void push(int val) {
// 将前面小于自己的元素都删除
while (!q.isEmpty() && q.getLast() < val) q.pollLast();
q.addLast(val);
}
public int max() {
return q.getFirst();
}
public void pop(int val) {
// 因为我们想删除的队头元素 val 可能已经不存在了,所以这时候就不用删除了
if (val == q.getFirst()) q.pollFirst();
}
}
public ArrayList<Integer> maxInWindows(int[] num, int k) {
ArrayList<Integer> res = new ArrayList();
if (k == 0) return res;
MonotonicQueue w = new MonotonicQueue();
for (int i = 0; i < num.length; i++) {
//先填满窗口的前 k - 1
if (i < k - 1) w.push(num[i]);
else {
// 窗口向前滑动,加入新数字
w.push(num[i]);
// 记录当前窗口的最大值
res.add(w.max());
// 移出旧数字
w.pop(num[i - k + 1]);
}
}
return res;
}
}