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
}