第十二天是周日休息
239. 滑动窗口最大值
单调队列经典题
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length;
int[] res = new int[n - k + 1];
Deque<Integer> q = new LinkedList<>(); // q里存这个元素在nums中的索引
for(int i = 0; i < n; i++){
// 维护队列的有效性。如果队列不为空,并且队列首部的索引对应的元素已经不在滑动窗口内,则将其从队列中删除。
if(!q.isEmpty() && q.getFirst() < i - k + 1){
q.pollFirst();
}
// 保证队列中的元素是非增的
while(!q.isEmpty() && nums[q.getLast()] < nums[i]){
q.pollLast();
}
q.addLast(i);
if(i >= k - 1){ // 当遍历的元素足够多,能够构成一个完整的滑动窗口时
res[i - k + 1] = nums[q.getFirst()];
}
}
return res;
}
}
347. 前 K 个高频元素
Java中优先队列是用小根堆实现的
class Solution {
public int[] topKFrequent(int[] nums, int k) {
HashMap<Integer, Integer> valToFreq = new HashMap<>(); // <nums中的元素,该元素出现的频率>
for(int num : nums){
valToFreq.put(num, valToFreq.getOrDefault(num, 0) + 1);
}
PriorityQueue<Map.Entry<Integer, Integer>> pq = new PriorityQueue<>((entry1, entry2) ->
{return entry1.getValue().compareTo(entry2.getValue());
}); // 队列按照键值对中的值(元素出现频率)从小到大排序
for(Map.Entry<Integer, Integer> entry : valToFreq.entrySet()){
pq.offer(entry);
if(pq.size() > k){
// 弹出最小元素,维护队列内是k个频率最大的元素
pq.poll();
}
}
int[] res = new int[k];
for(int i = k - 1; i >= 0; i--){
// res 数组中存储前k个最大元素
res[i] = pq.poll().getKey();
}
return res;
}
}