239. 滑动窗口最大值 (一刷至少需要理解思路)
题目链接:239. 滑动窗口最大值 - 力扣(LeetCode)
思路:保证在队列的fornt段是最大值,每次要pop时,比较是不是fornt端的元素,若不是则不pop
在push是,比较该元素是不是比back端的大,若大则移出back段的元素,直到back端没有比他更大的。
class MyQueue{
Deque<Integer> deque = new LinkedList<>();
void poll(int val){
if(!deque.isEmpty() && val == deque.peek()){
deque.poll();
}
}
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();
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;
}
}
347.前 K 个高频元素
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
思路:
用大顶堆或小顶堆来解决前k个大的或者小的元素。
大顶堆需要保证全部有序,小顶堆只用保证前K个元素有序,
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer,Integer> map = new HashMap<>();
for(int num:nums){
map.put(num,map.getOrDefault(num,0)+1);
}
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[] res = new int[k];
for(int i = k-1;i>=0;i--){
res[i] = pq.poll()[0];
}
return res;
}
}
总结:最后小顶堆中是K个从小到大的使用最频繁的数据,所以出队列后要从大到小进入数组。