T1 59 - I. 滑动窗口的最大值
滑动窗口每次移动元素的增添符合队列先进先出的特点
创建一个队列保证
1.仅包含滑动窗口的元素
2.每次添加元素队列里小于新增加元素则删除
Queue | Deque | |
---|---|---|
添加元素到队尾 | add(E e) / offer(E e) | addLast(E e) / offerLast(E e) |
取队首元素并删除 | E remove() / E poll() | E removeFirst() / E pollFirst() |
取队首元素但不删除 | E element() / E peek() | E getFirst() / E peekFirst() |
添加元素到队首 | 无 | addFirst(E e) / offerFirst(E e) |
取队尾元素并删除 | 无 | E removeLast() / E pollLast() |
取队尾元素但不删除 | 无 | E getLast() / E peekLast() |
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums.length==0 || k==0) return new int[0]; //空值处理
Deque<Integer> queue = new LinkedList<Integer>(); //滑动窗口队列
int[] res = new int[nums.length-k+1]; //每次滑动后的最大值
//为形成窗口
for(int i=0;i<k;i++){
//队列中小于新增元素删除
//保证队列单调不增,队首最大
while(!queue.isEmpty() && queue.peekLast() < nums[i])
queue.removeLast();
queue.addLast(nums[i]);
}
res[0] = queue.peekFirst();
//形成滑动窗口
for(int i=k;i<nums.length;i++){
//更新滑动窗口,需删除滑动窗口原来的第一位
//由于须保证每次小于新增元素要删去
//则原来的第一位可能在之前已经删除了,所以一判断一下
if(queue.peekFirst() == nums[i-k])
queue.removeFirst();
//队列中小于新增元素删除
//保证队列单调不增,队首最大
while(!queue.isEmpty() && queue.peekLast()<nums[i])
queue.removeLast();
queue.addLast(nums[i]);
res[i-k+1] = queue.peekFirst();
}
return res;
}
}
T2 59 - II. 队列的最大值
和上一题核心思路一致
class MaxQueue {
Queue<Integer> queue; //存放数字的入队顺序
Deque<Integer> deque; //保证单调不减双端队列,快速拿去最大值(队首)
public MaxQueue() {
queue = new LinkedList<Integer>();
deque = new LinkedList<Integer>();
}
public int max_value() {
//双端队列非空弹出队首否则-1
return deque.isEmpty() ? -1: deque.peekFirst();
}
public void push_back(int value) {
queue.add(value);
//双端保证单调不减
//每次小于新增元素的双端队列元素删除
while(!deque.isEmpty() && deque.peekLast()<value)
deque.removeLast();
deque.addLast(value);
}
public int pop_front() {
if(queue.isEmpty()) return -1;
//由于保持单调不减的双端队列
//可能在添加新元素时删除了pop_front需求队首
//所以和存放数字顺序队列的队首做比较
//相同则同时出队,不同则双端不处理 equals比较地址和值
if(queue.peek().equals(deque.peekFirst()))
deque.removeFirst();
return queue.remove();
}
}