代码随想录算法训练营第十二天|栈和队列 part3

86 阅读2分钟

239. 滑动窗口最大值

题目链接:239. 滑动窗口最大值 - 力扣(LeetCode)

第一想法

根据k值构建一个新的数组

求新数组的最大值

改变数组的值,去掉第一个数,并且在末尾添加一个元素

思路

这一题写起来完全无从下手

看了思路还是没法写出来

最后一边看答案一边写出来的

这题可以创建一个单调队列,即队列中是单调递减的

再创建三个方法,入队,出队,取最值

image-20230327230839075

  • 入队

    保证队列是递减排序的

    即,如果目前队中有小于value的元素,则将元素出队,将value入队

  • 出队

    如果当前value是队首,则出队,否则不动

  • 取最值

    因为队首是最大值,所以,取队首的值

最后只需要遍历一遍数组

对每一个元素进行相应的入队和出队操作即可

var maxSlidingWindow = function(nums, k) {
    class MonoQueue{
        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){
            if(value === this.queue[0]){
                this.queue.shift();
            }
        }
        // 取最值
        getmax(){
            return this.queue[0];
        }
    }
    let thequeue = new MonoQueue();
    let arr = [];
    let i = 0, j = 0;
    // 初始窗口值入队
    while(j < k){
        thequeue.enqueue(nums[j++])
    }
    // 取初始窗口中的最大值
    arr.push(thequeue.getmax());
    // 遍历数组进行入队出队取最值操作
    while(j < nums.length){
        thequeue.enqueue(nums[j]);
        thequeue.dequeue(nums[i]);
        arr.push(thequeue.getmax());
        i++,j++;
    }
    return arr;
};

总结

这题的思路很重要

写的时候虽然看了几眼答案的思路,不过自己写还是出现了问题

主要是没有理解好入队的方法如何操作

这里是需要维护一个降序排列的对列

所以新的元素入队并不是单纯的和队首元素比较就行

而是将其放入合适的位置去

这里相当于创建了一个队列,该队列有自己的入队和出队的方法,再用这个队列去遍历数组,从而得到答案

347.前K个高频元素

题目链接:347. 前 K 个高频元素 - 力扣(LeetCode)

第一想法

遍历

用map存储出现的次数

思路

JS里面没有堆

实现好复杂

先往后放放