开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情 1.滑动窗口的最大值
题目描述
解题思路
1.我们自定义一个单调递减队列,存放可能是最大值的元素。
2.当移动滑动窗口时,如果出滑动窗口时的元素正好等于队列对头元素,把该元素从队列移除,如果进入滑动窗口的元素把队列头元素大,那么移除队列所有元素,再把该元素入队列。
3.滑动窗口移动时,把每个队列头元素加入结果数组中。
var maxSlidingWindow = function(nums, k) {
class Dequeue {
queue;
constructor(){
this.queue = []
}
enqueue(value){
let back = this.queue[this.queue.length - 1]
while(back!==undefined&&back<value){
this.queue.pop()
back = this.queue[this.queue.length - 1]
}
this.queue.push(value)
}
dequeue(value){
let front = this.front()
if(front === value){
this.queue.shift()
}
}
front(){
return this.queue[0]
}
}
let helperDequeue = new Dequeue()
let i = 0,j =0;
let result = []
while(j<k){
helperDequeue.enqueue(nums[j++])
}
result.push(helperDequeue.front());
while (j < nums.length) {
helperDequeue.enqueue(nums[j]);
helperDequeue.dequeue(nums[i]);
result.push(helperDequeue.front());
i++, j++;
}
return result;
};
2.前k个高频元素
题目描述
解题思路
1.使用map统计每个数字出现的次数。
2.理解大顶堆小顶堆的含义:堆是一棵完全二叉树,树中每个结点的值都不小于(或不大于)其左右孩子的值。 如果父亲结点是大于等于左右孩子就是大顶堆,小于等于左右孩子就是小顶堆。
3.因为要统计最大前k个元素,只有小顶堆每次将最小的元素弹出,最后小顶堆里积累的才是前k个最大元素。
var topKFrequent = function(nums, k) {
const map = new Map();
for(const num of nums) {
map.set(num, (map.get(num) || 0) + 1);
}
// 创建小顶堆
const priorityQueue = new PriorityQueue((a, b) => a[1] - b[1]);
// entry 是一个长度为2的数组,0位置存储key,1位置存储value
for (const entry of map.entries()) {
priorityQueue.push(entry);
if (priorityQueue.size() > k) {
priorityQueue.pop();
}
}
const ret = [];
for(let i = priorityQueue.size() - 1; i >= 0; i--) {
ret[i] = priorityQueue.pop()[0];
}
return ret;
};
class PriorityQueue {
constructor(compareFn){
this.queue = []
this.compareFn = compareFn
}
push(item){
this.queue.push(item)
let index = this.queue.length - 1
let parent = Math.floor((index - 1) / 2)
// 上浮
while(parent>=0&&this.compare(parent,index)>0){
[this.queue[index],this.queue[parent]] = [this.queue[parent],this.queue[index]]
index = parent
parent = Math.floor((index-1)/2)
}
}
pop(){
const ret = this.queue[0]
this.queue[0] = this.queue.pop()
let index = 0;
let left = 1;
let selectedChild = this.compare(left,left+1)>0?left+1:left
// 下沉
while(selectedChild !== undefined && this.compare(index, selectedChild) > 0) {
// 交换
[this.queue[index], this.queue[selectedChild]] =
[this.queue[selectedChild], this.queue[index]];
index = selectedChild;
left = 2 * index + 1;
selectedChild = this.compare(left, left + 1) > 0 ? left + 1 : left;
}
return ret;
}
size(){
return this.queue.length
}
compare(index1, index2){
if (this.queue[index1] === undefined) {
return 1;
}
if (this.queue[index2] === undefined) {
return -1;
}
return this.compareFn(this.queue[index1], this.queue[index2]);
}
}