239. 滑动窗口最大值
题解及想法
如图,自定义队列:
- pop(value):当窗口移除的元素value等于单调队列的出口元素,此时队列弹出元素,否则不做操作。
- push(value):单push的元素value大于入口元素的数值,队列入口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止
//自定义数组
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() && val > deque.getLast()){
deque.removeLast();
}
deque.add(val);
}
//队列队顶元素始终为最大值
int peek() {
return deque.peek();
}
}
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
//存放结果元素的数组
int[] res = new int[nums.length - k + 1];
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;
}
}
347.前 K 个高频元素
题解及想法
1.通过map统计数值中各个数值出现的次数,key保存数组的数值,value则保存该数组出现的次数。
2.遍历map,通过小顶堆来维护前k个高频元素,当小顶堆的元素小于k个是时,往小顶堆里加元素,当小顶堆元素大于等于k个时,map的元素与小顶堆的顶点元素进行对比(小顶堆顶点元素为最小元素),当map的元素大于小顶堆顶点元素时,弹出顶点元素,map的元素加入小顶堆,当map的元素小于小顶堆顶点元素时,不做操作,直到遍历完map的元素,此时小顶堆了的元素即为前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<>((p1,p2) -> p1[1] - p2[1]);
for(Map.Entry<Integer,Integer> entry : map.entrySet()){
if(pq.size() < k){
pq.add(new int[]{entry.getKey(),entry.getValue()});
}else{
if(pq.peek()[1] < entry.getValue()){
pq.poll();
pq.add(new int[]{entry.getKey(),entry.getValue()});
}
}
}
int[] ans = new int[k];
for(int i=k-1;i>=0;i--){//依次弹出小顶堆,先弹出的是堆的根,出现次数少,后面弹出的出现次数多
ans[i] = pq.poll()[0];
}
return ans;
}
}