day 12 栈与队列3
一、239. 滑动窗口最大值
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
MyQueue mq = new MyQueue();
int num = 0;
int[] arr = new int[nums.length - k +1];
//先填入k个数据到mq中
for(int i = 0; i < k;i++){
mq.push(nums[i]);
}
arr[num++] = mq.peek();
//对单调队列进行循环进行操作
for(int i = k; i < nums.length; i++){
mq.poll(nums[i - k]);
mq.push(nums[i]);
arr[num++] = mq.peek();
}
return arr;
}
}
class MyQueue{
Deque<Integer> deque = new LinkedList<>();
//加入一个元素,需要进行排队,比他小的都弹出。
public void push(int value){
while(!deque.isEmpty() && value > deque.getLast()){
deque.removeLast();
}
deque.add(value);
}
//如果队列头元素也就是最大元素被弹出才需要真正的被弹出,
//其他元素在最大元素进入的时候已经被移除队列
public void poll(int value){
if(!deque.isEmpty() && value == deque.peek()){
deque.poll();
}
}
public int peek(){
return deque.peek();
}
}
采用单调队列进行操作,看注释。
二、347. 前 K 个高频元素
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer,Integer> map = new HashMap<>();//key为数组元素值,val为对应出现次数
for(int num : nums){
map.put(num,map.getOrDefault(num,0)+1);
}
PriorityQueue<int[]> pq = new PriorityQueue<>((pair1,pair2)->pair1[1]-pair2[1]);
for(Map.Entry<Integer,Integer> entry:map.entrySet()){//小顶堆只需要维持k个元素有序
if(pq.size()<k){//小顶堆元素个数小于k个时直接加
pq.add(new int[]{entry.getKey(),entry.getValue()});
}else{
if(entry.getValue()>pq.peek()[1]){//当前元素出现次数大于小顶堆的根结点(这k个元素中出现次数最少的那个)
pq.poll();//弹出队头(小顶堆的根结点),即把堆里出现次数最少的那个删除,留下的就是出现次数多的了
pq.add(new int[]{entry.getKey(),entry.getValue()});
}
}
}
int[] ans = new int[k];
for(int i=k-1;i>=0;i--){//依次弹出小顶堆,先弹出的是堆的根,出现次数少,后面弹出的出现次数多
ans[i] = pq.poll()[0];
}
return ans;
}
}
使用PriorityQueue实现小顶堆,需要回头再看。