算法打卡第十三天 栈与队列3 力扣239,347

77 阅读1分钟

239. 滑动窗口最大值 (困难难度) 一开始直接用的滑动窗口方法,发现直接超时了。 采用单调队列,不断筛选值,减少多余的遍历操作。

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var maxSlidingWindow = function(nums, k) {
    class monoQueue {
        constructor () {
            this.queue = [];
        }
        pushQueue(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);
        }
        popQueue(value) {
            // 如果遇到最大值和当前值相同时
            // 去除第一个值,保证只有一个最大值
            let front = this.front();
            if (front === value) {
                this.queue.shift();
            }
        }
        front() {
            // 最大值就是第一个值
            return this.queue[0];
        }
     }
    let resArr = [];
     let myQueue = new monoQueue();
     let i = 0, j = 0;
     for (; i < k; i++) {
         myQueue.pushQueue(nums[i]);
     }
     resArr.push(myQueue.front());

     while (i < nums.length) {
        myQueue.pushQueue(nums[i]);
        myQueue.popQueue(nums[j]);
        resArr.push(myQueue.front());
        i++,j++;
     }
     return resArr;
     
};

347. 前 K 个高频元素(中等难度) 一开始直接是用map收集元素,然后遍历map,重新排序map,发现不符合题目的时间要求。 后面看了大佬的桶排序,学着用桶排序做了一遍

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var topKFrequent = function (nums, k) {
    let map = new Map();
    for (let i = 0; i < nums.length; i++) {
        if (map.has(nums[i])) {
            map.set(nums[i], map.get(nums[i]) + 1);
        } else {
            map.set(nums[i], 1);
        }
    }
    if (nums.length < k) {
        return [...map.keys()];
    }
    return bucketSort(map, k);
    // 桶排序
    

};

var bucketSort = (map, k) => {
        let arr = [], res = []
        map.forEach((value, key)=>{
            // 按照出现次数作为下表,放进每一个桶里
            if (!arr[value]) {
                arr[value] = [key];
            } else {
                arr[value].push(key);
            }
        })
        
        // 倒序遍历获取出现频率最大的前k个数
        for (let i = arr.length - 1; i >= 0 && res.length < k; i--) {
            if (arr[i]) {
                res.push(...arr[i])
            }
        }
        return res
    }