java中Deque双端队列
常用的函数补充:
getLast()
removeLast()
addFirst()
leetcode 239
题目链接
滑动窗口最大值
思路:
- 用优先队列/大顶堆?——不行,每次往后移动的时候,弹出很麻烦
- ∴ \therefore ∴ 用队列
- 双端队列(单调栈的一个延申),
- 每次向右移动时,把窗口左端的值从队列左端剔除,把队列右边小于窗口右端的值全部剔除
- 队列最左端的数始终是窗口内最大的数
push(val)
:.push(val)
的val
值 > > > 队头元素,将队头元素弹出;直到val
≤ \le ≤ 队头元素pop(val)
:如果窗口移除的元素val
= = = 单调队列的出口元素,那么队列弹出元素,否则不用任何操作
note: 有点小难,多练几遍!!
class MyDeque {
Deque<Integer> deque;
MyDeque() {
deque = new ArrayDeque<>();
}
public void add(int x) {
while (!deque.isEmpty() && x > deque.getLast()) //decreasing
deque.removeLast();
deque.add(x);
}
public int peek() {
return deque.peek();
}
public void remove(int x) {
if (!deque.isEmpty() && x == deque.peek())
deque.remove();
}
}
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
MyDeque myQ = new MyDeque();
//record the len of the array which should be return
int len = nums.length - k + 1;
int[] res = new int[len];
int n = 0;
for (int i = 0; i < k; ++i)
myQ.add(nums[i]);
res[n++] = myQ.peek();
for (int i = k; i < nums.length; ++i) {
myQ.remove(nums[i - k]);
myQ.add(nums[i]);
res[n++] = myQ.peek();
}
return res;
}
}
java 中堆/优先队列
什么是堆?
- 一棵完全二叉树,树中每个结点的值都不小于(或不大于)其左右孩子的值。 如果父亲结点是大于等于左右孩子就是大顶堆,小于等于左右孩子就是小顶堆。
- 堆头最大——大顶堆;堆头最小——小顶堆
java中实现:
java.util.PriorityQueue<>
:优先队列- 默认是小根堆,大根堆写法:
new PriorityQueue<>(Collections.reverseOrder())
- 默认是小根堆,大根堆写法:
定义及初始化
Queue<Integer> q1 = new PriorityQueue<Integer>(); //优先队列,默认小根堆(从小到大)
Queue<Integer> q2 = new PriorityQueue<Integer>(Collections.reverseOrder()); //大根堆
leetcode 347
题目链接
前K个高频元素
思路:
- 小/大顶堆,优先队列
- 用
map
先来记录每个数的出现频次 - 再用优先队列完成排序
大根堆代码示例如下(主要看PriorityQueue定义!!!)
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
//统计frequence
for (int i = 0; i < nums.length; ++i)
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
// 大根堆
Queue<int[]> queue = new PriorityQueue<>((x, y) -> {
return y[1] - x[1];
});
for (Map.Entry<Integer, Integer> x : map.entrySet()) {
int[] temp = {x.getKey(), x.getValue()};
queue.add(temp);
}
int[] res = new int[k];
for (int i = 0; i < k; ++i)
res[i] = queue.remove()[0];
return res;
}
}