使用单调队列,堆头元素为当前窗口内最大的元素,当遍历数组时比较当前元素与堆头元素的大小,若大,则移除队内元素,若小,先判断窗口内元素是否是窗口最大值,若不是则直接加入队列,若是则pop堆头元素再加入当前元素
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums.length == 1) {
return nums;
}
int[] result = new int[nums.length + 1 - k];
int num = 0;
MyQueue myQueue = new MyQueue();
for (int i = 0; i < k; i++) {
myQueue.add(nums[i]);
}
result[num++] = myQueue.peek();
for (int i = k; i < nums.length; i++) {
myQueue.poll(nums[i - k]);
myQueue.add(nums[i]);
result[num++] = myQueue.peek();
}
return result;
}
}
class MyQueue {
Deque<Integer> deque = new LinkedList<>();
// 弹出元素时,判断弹出元素是否与队列头部的元素相等,相等则弹出,同时判断列是否为空
void poll(int val) {
if (!deque.isEmpty() && deque.peek() == val) {
deque.poll();
}
}
// 添加元素时,判断当前元素是否比队列头部元素大,若是则将队列元素弹出
void add(int val) {
while (!deque.isEmpty() && deque.getLast() < val) {
deque.removeLast();
}
deque.add(val);
}
int peek() {
return deque.peek();
}
}
使用小顶堆,小顶堆的大小设置为k,遍历数组,若当前元素大于堆头元素则弹出堆头元素,最后堆内元素即位结果。
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
int[] result = new int[k];
for (int num : nums) {
map.put(num, map.getOrDefault(num,0) + 1);
}
// 创建小顶堆
PriorityQueue<int[]> pq = new PriorityQueue<>((nums1, nums2) -> nums1[1] - nums2[1]);
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
// 如果堆内元素小于k,直接添加元素
if (pq.size() < k) {
pq.add(new int[]{entry.getKey(),entry.getValue()});
} else {
// 如果map当前元素出现次数比堆头元素大,弹出堆头元素,加入当前元素
if (entry.getValue() > pq.peek()[1]) {
pq.poll();
pq.add(new int[]{entry.getKey(),entry.getValue()});
}
}
}
for (int i = 0; i < k; i++) {
result[i] = pq.poll()[0];
}
return result;
}
}