239. 滑动窗口最大值
思路:构建一个单调队列来做,保证最大值永远都在队列前面。那么如何构建呢?我们可以每次比较推入的元素与队列尾部元素进行比较,如何比他小则推入,如果比他大则将尾部元素从尾部推出来。
看代码随想录还有另外一种思路,但是那种比较难一点。二刷再看看
class MyQueue {
Deque<Integer> deque = new LinkedList<>();
//弹出元素时,比较当前要弹出的数值是否等于队列出口的数值,如果相等则弹出
//同时判断队列当前是否为空
void poll(int val) {
if (!deque.isEmpty() && val == deque.peek()) {
deque.poll();
}
}
//添加元素时,如果要添加的元素大于入口处的元素,就将入口元素弹出
//保证队列元素单调递减
//比如此时队列元素3,1,2将要入队,比1大,所以1弹出,此时队列:3,2
void add(int val) {
while (!deque.isEmpty() && val > deque.getLast()) {
deque.removeLast();
}
deque.add(val);
}
//队列队顶元素始终为最大值
int peek() {
return deque.peek();
}
}
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums.length == 1) {
return nums;
}
int len = nums.length - k + 1;
//存放结果元素的数组
int[] res = new int[len];
int num = 0;
//自定义队列
MyQueue myQueue = new MyQueue();
//先将前k的元素放入队列
for (int i = 0; i < k; i++) {
myQueue.add(nums[i]);
}
res[num++] = myQueue.peek();
for (int i = k; i < nums.length; i++) {
//滑动窗口移除最前面的元素,移除是判断该元素是否放入队列
myQueue.poll(nums[i - k]);
//滑动窗口加入最后面的元素
myQueue.add(nums[i]);
//记录对应的最大值
res[num++] = myQueue.peek();
}
return res;
}
}
题目链接/文章讲解/视频讲解:programmercarl.com/0239.%E6%BB…
347.前 K 个高频元素
【思路】:先将每一个元素遍历一遍,记录其个数到map集合中,然后遍历map集合,将每个key,value转换为集合存储到最小堆(优先级队列中),每次遍历都判断最小堆的大小有没有大于k,如果k则将最小堆中的最小元素弹出(这里其实就是保证最小堆的元素总和与k的值相等,到时候直接遍历最小堆则是所需要的前k个元素)
如果基于最大堆实现,则直接将map集合放在最大堆中,到时候弹出前k个元素即可,相当于排了一个序再取前k个元素。
class Solution {
public int[] topKFrequent(int[] nums, int k) {
// 优先级队列
// lambda 表达式设置优先级队列从大到小存储 o1 - o2 为从小到大,o2 - o1 反之
PriorityQueue<int[]> pq = new PriorityQueue<>((o1, o2) -> o1[1] - o2[1]);
int[] res = new int[k]; // 答案数组为 k 个元素
Map<Integer, Integer> map = new HashMap<>(); // 记录元素出现次数
for(int num : nums) map.put(num, map.getOrDefault(num, 0) + 1);
for(var x : map.entrySet()) { // entrySet 获取 k-v Set 集合
// 将 kv 转化成数组
int[] tmp = new int[2];
tmp[0] = x.getKey();
tmp[1] = x.getValue();
pq.offer(tmp);
// 下面的代码是根据小根堆实现的,我只保留优先队列的最后的k个,只要超出了k我就将最小的弹出,剩余的k个就是答案
if(pq.size() > k) {
pq.poll();
}
}
for(int i = 0; i < k; i ++) {
res[i] = pq.poll()[0]; // 获取优先队列里的元素
}
return res;
}
}
题目链接/文章讲解/视频讲解:programmercarl.com/0347.%E5%89…
总结
栈:先进后出 队列:先进先出 两个都可以右双向队列实现