一、学习双端队列
java.util接口 Deque<E>
类型参数:E
- 此 collection 中保存的元素类型
所有已知实现类:ArrayDeque, LinkedBlockingDeque, LinkedList
- 一个线性 collection,支持在两端插入和移除元素。名称 deque 是“double ended queue(双端队列)”的缩写,通常读为“deck”。大多数 Deque 实现对于它们能够包含的元素数没有固定限制,但此接口既支持有容量限制的双端队列,也支持没有固定大小限制的双端队列。
第一个元素(头部) | 最后一个元素(尾部) | |||
抛出异常 | 特殊值 | 抛出异常 | 特殊值 | |
插入 | addFirst(e) | offerFirst(e) | addLast(e) | offerLast(e) |
移除 | removeFirst() | pollFirst() | removeLast() | pollLast() |
检查 | getFirst() | peekFirst() | getLast() | peekLast() |
- 此接口扩展了
Queue
接口。在将双端队列用作队列时,将得到 FIFO(先进先出)行为。将元素添加到双端队列的末尾,从双端队列的开头移除元素。从 Queue 接口继承的方法完全等效于 Deque 方法,如下表所示:
Queue 方法 | 等效 Deque 方法 |
add(e) | addLast(e) |
offer(e) | offerLast(e) |
remove() | removeFirst() |
poll() | pollFirst() |
element() | getFirst() |
peek() | peekFirst() |
- 双端队列也可用作 LIFO(后进先出)堆栈。应优先使用此接口而不是遗留
Stack
类。在将双端队列用作堆栈时,元素被推入双端队列的开头并从双端队列开头弹出。堆栈方法完全等效于 Deque 方法,如下表所示:
堆栈方法 | 等效 Deque 方法 |
push(e) | addFirst(e) |
pop() | removeFirst() |
peek() | peekFirst() |
注意,在将双端队列用作队列或堆栈时,peek
方法同样正常工作;无论哪种情况下,都从双端队列的开头抽取元素。
与 List
接口不同,此接口不支持通过索引访问元素。不能像list.get(i)这样
二、题目
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值。
思路:设一个双端队列,一个结果数组,一个临时变量max。双端队列用于存放数组元素的下标;max用于记录最大值
先找出前k个的最大值,赋给max,然后双端队列将该最大值的下标放到nums数组里,最后再赋给结果数组;
调用过滤函数clean _deque,用于找出滑动数组里最大的,和去掉不需要的元素(滑动着走的,元素也要改变)
这样双端队列的getFirst就是我们想要的下标;
最后返回数组。
import java.util.ArrayDeque;
import java.util.Arrays;
public class slidingWindow {
public static void main(String[] args) {
slidingWindow ts = new slidingWindow();
int[] nums = { 1, 3, -1, -3, 5, 3, 6, 7 };
nums = ts.maxSlidingWindow(nums, 3);
System.out.println(Arrays.toString(nums));
}
ArrayDeque<Integer> deq = new ArrayDeque<Integer>();
int[] nums;
public void clean_deque(int i, int k) {
if (!deq.isEmpty() && deq.getFirst() == i - k) {// 如果索引超过窗口范围
deq.removeFirst();
}
while (!deq.isEmpty() && nums[i] > nums[deq.getLast()]) {
deq.removeLast();
}
}
public int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length;
if (k == 1) {
return nums;
}
this.nums = nums;// 成员变量,在这里赋值,以便上面的方法也能访问
int max_idx = 0;
for (int i = 0; i < k; i++) {
clean_deque(i, k);
deq.addLast(i);
if (nums[i] > nums[max_idx])
max_idx = i;
}
int[] output = new int[n - k + 1];
output[0] = nums[max_idx];
for (int i = k; i < n; i++) {
clean_deque(i, k);
deq.addLast(i);
output[i - k + 1] = nums[deq.getFirst()];
}
return output;
}
end.