学习队列
follow:代码随想录
239 滑动窗口最大值
题目描述:
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
解析:
单调队列:单调递减队列或单调递增队列——使用Deque
- 思路:实现一个单调递减的队列,即将每个滑动窗口按照顺序进行单调递减的排列。
- push:首先将第一个窗口内的元素,按照单调性添加到队列中。之后对于每个元素,与队头元素进行判断,如果大于队头元素,则将队列中的元素都弹出,再压入该元素;否则按照单调递减的顺序加入到队列中
- pop:如果窗口中移出的元素与队头元素相等,则队列弹出队头元素,否则不用进行任何操作
解答:
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
int length = nums.length;
Deque<Integer> record = new LinkedList<>();
int[] result = new int[length - k + 1];
int count = 0;
//初始化
for(int i = 0; i < k; i++){
while(!record.isEmpty() && record.peekLast() < nums[i]){
record.pollLast();
}
record.offerLast(nums[i]);
}
result[count++] = record.peekFirst();
//处理每个元素
for(int i = k; i < length; i++){
//先poll
if(record.peekFirst() == nums[i - k]){
record.pollFirst();
}
while(!record.isEmpty() && record.peekLast() < nums[i]){
record.pollLast();
}
//再push
record.offerLast(nums[i]);
//最后填写最大值
result[count++] = record.peekFirst();
}
return result;
}
}
347 前k个高频元素
题目描述:
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
解析:
思路:
- 统计数组中的元素统计次数
- 给所有次数排序
- 输出前k个元素
首先可以使用Map保存元素出现的次数,使用优先级队列对出现的次数进行排序。
优先级队列——PriorityQueue
- 使用数组实现一个小顶堆(完全二叉树,父节点比两个子节点的权重小或是相等)
- 可以使用同queue的操作:peek()/element(),poll()/remove(),add()/offer()
- 具体Java中的集合(四)PriorityQueue常用方法
解答:
public int[] topKFrequent(int[] nums, int k) {
//使用Map统计出现的次数
Map<Integer,Integer> record = new HashMap<>();
for(int i : nums){
record.put(i, record.getOrDefault(i, 0) + 1);
}
//构造优先级队列——小顶堆
//自定义排序
PriorityQueue<Map.Entry<Integer,Integer>> queue = new PriorityQueue<>(new Comparator<>(){
public int compare(Map.Entry<Integer,Integer> i,Map.Entry<Integer,Integer> j){
return i.getValue() - j.getValue();
}
});
//将元素放到优先级队列中
for(Map.Entry<Integer,Integer> entry : record.entrySet()){
queue.offer(entry);
//当k+1个时,弹出队头
if(queue.size() > k){
queue.poll();
}
}
int[] result = new int[k];
int count = 0;
while(queue.peek() != null){
result[count++] = queue.poll().getKey();
}
return result;
}