239. 滑动窗口最大值
思路
构建一个适用于本题的单调递减非去重队列
- 从队尾执行 push 操作时,从队尾开始,所有小于当前元素的都会被出队列 --> 保证队列内所有元素单调递减
- 从对头执行 pop 操作时,判断队头元素是否等于当前元素,等于就出队列,不等于则不执行 --> 对于单调递减队列,队头就是最大元素,不能随意出队列,除非要出的就是最大数值;且本题中只要求最大值,不要求其他的数值。
注意,单调递减队列不能去重,否则会导致移除元素时误将窗口还在的数据被移除出去
解题思路
复杂度
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( k ) ) O(k)) O(k))
代码
Java
// 单调递减非去重队列
class MyDeque {
Deque<Integer> deque = new LinkedList<Integer>();
void push(int val) {
while(!deque.isEmpty() && deque.getLast() < val) {
deque.removeLast();
}
deque.addLast(val);
}
void pop(int val) {
if(!deque.isEmpty() && deque.peek() == val) {
deque.removeFirst();
}
}
int getMax() {
return deque.peek();
}
}
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
// 构建滑动窗口
int len = nums.length - k + 1;
int[] result = new int[len];
int resIndex = 0;
// 构建单调递减队列
MyDeque myDeque = new MyDeque();
// 首先将初始窗口放到队列中
for(int i = 0; i < k; i++) {
myDeque.push(nums[i]);
}
result[resIndex++] = myDeque.getMax();
// 窗口遍历数组,队列 push 窗口新增元素,pop 窗口移除元素
for (int i = k; i < nums.length; i++) {
myDeque.pop(nums[i - k]);
myDeque.push(nums[i]);
result[resIndex++] = myDeque.getMax();
}
return result;
}
}
347.前 K 个高频元素
思路
- 通过哈希表(基于map实现)统计数组各个元素的出现次数
- 通过小顶堆(出现次数按从队头到队尾的顺序是从小到大排,出现次数最低的在队头)获取前 k 个高频元素
- 优先队列存储二元组(数组模拟),存储时,如果当前元素的频次大于堆顶且优先队列内长度大于等于 k,则队头 poll,始终保持队列长度小于等于 k
解题思路
复杂度
时间复杂度: O ( n l o g k ) O(nlogk) O(nlogk)
空间复杂度: O ( n ) O(n) O(n)
代码
Java
class Solution {
public int[] topKFrequent(int[] nums, int k) {
// 通过哈希表(基于map实现)统计数组各个元素的出现次数
Map<Integer, Integer> map = new HashMap<>();
for(int num: nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
// 通过小堆顶(出现次数按从队头到队尾的顺序是从小到大排,出现次数最低的在队头)获取前 k 个高频元素
// 优先队列存储二元组(数组模拟),存储时,如果当前元素的频次大于堆顶且优先队列内长度大于等于 k,则队头 poll,始终保持队列长度小于等于 k
// 这样队列内就是前 k 个高频元素
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()});
}
}
int[] result = new int[k];
for(int i = 0; i < k; i++) {
result[i] = pq.poll()[0];
}
return result;
}
}