前言
第一次遇见这种数据结构,记录一下。
比如:滑动窗口和高频元素,这两个题我觉得都挺接地气。
滑动窗口这题主要是获取每个窗口中的最大数并记录,和时序有关。
高频元素就像是 top-k
或者 tfidf
,都有其实用场景。
实现
单调递减队列
单调队列有着巧妙的插入方式。
- 插入: 如果插入的比末尾数大,就向前清理,维护递减序列
- 弹出: 如果弹出的是头部数(也就是最大的那个),就正常弹出,其他的忽略
由于维护了有序性,所以弹出的时候不可能出现弹出数比当前数更大的情况,其他的都被最大的那个删掉了,所以其他的可以忽略。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class MyQueue{ Deque<Integer> deque = new LinkedList<>();
void poll(int num){ if(!deque.isEmpty() && num == deque.peek()){ deque.poll(); } }
void push(int num){ while(!deque.isEmpty() && num > deque.getLast()){ deque.removeLast(); } deque.add(num); }
int peek(){ return deque.peek(); } }
|
优先级队列(维护前 k 个最大的)
- 插入: 如果插入的比队列中最小的大,弹出小的,插入这个
1 2 3 4 5 6 7 8 9 10 11 12 13
| PriorityQueue<int[]> pq = new PriorityQueue<>((pair1, pair2) -> pair1[1] - pair2[1]);
for(Map.Entry<Integer, Integer> entry : map.entrySet()){ if(pq.size() < k){ pq.add(new int[]{entry.getKey(), entry.getValue()}); }else{ if(entry.getValue() > pq.peek()[1]){ pq.poll(); pq.add(new int[]{entry.getKey(), entry.getValue()}); } } }
|