队列的概念
先进先出原则的有序集合
添加新元素的一端称为队尾,另一端称为队首
队列的实现
// 数组形式
class Queue {
constructor () {
// 用于存储队列数据
this.queue = []
this.count = 0
}
// 入队方法
enQueue (item) {
this.queue[this.count++] = item
}
// 出队方法
deQueue () {
if (this.isEmpty()) {
return
}
// 删除 queue 的第一个元素
// delete this.queue[0]
// 利用 shift() 移除数组的第一个元素
this.count--
return this.queue.shift()
}
isEmpty () {
return this.count === 0
}
// 获取队首元素值
top () {
if (this.isEmpty()) {
return
}
return this.queue[0]
}
size () {
return this.count
}
clear () {
// this.queue = []
this.length = 0
this.count = 0
}
}
const q = new Queue()
对象实现方式
// 对象实现方式
lass Queue {
constructor () {
this.queue = {}
this.count = 0
// 用于记录队首的键
this.head = 0
}
// 入队方法
enQueue (item) {
this.queue[this.count++] = item
}
// 出队方法
deQueue () {
if (this.isEmpty()) {
return
}
const headData = this.queue[this.head]
delete this.queue[this.head]
this.head++
this.count--
return headData
}
isEmpty () {
return this.count === 0
}
clear () {
this.queue = {}
this.count = 0
this.head = 0
}
}
const q = new Queue()
双端队列
允许同时从队尾与队首两端进行存取操作的队列,操作更加灵活。
// 实现功能
addFront/addBack
removeFront/removeBack
frontTop/backTop
class Deque {
constructor () {
this.queue = {}
this.count = 0
this.head = 0
}
// 队首添加
addFront (item) {
this.queue[--this.head] = item
}
// 队尾添加
addBack (item) {
this.queue[this.count++] = item
}
// 队首删除
removeFront () {
if (this.isEmpty()) {
return
}
const headData = this.queue[this.head]
delete this.queue[this.head++]
return headData
}
// 队尾删除
removeBack () {
if (this.isEmpty()) {
return
}
const backData = this.queue[this.count - 1]
delete this.queue[--this.count]
// this.count-- 与 上一步 this.count - 1 合并
return backData
}
// 获取队首值
frontTop () {
if (this.isEmpty()) {
return
}
return this.queue[this.head]
}
// 获取队尾值
backTop () {
if (this.isEmpty()) {
return
}
return this.queue[this.count - 1]
}
isEmpty () {
return this.size() === 0
}
size () {
return this.count - this.head
}
}
const deq = new Deque()
题目
// 滑动窗口的最大值
/*
* 输入:nums=[1,3,-1,-3,5,3,6,7],k=3
* 输出:[3,3,5,5,6,7]
*/
/**
* @param {number[]} nums 传入数组
* @param {number} k 滑动窗口宽度
* @return {number[]}
*/
var maxSlidingWindow = function(nums, k) {
if (k <= 1) {
return nums
}
const result = []
const deque = []
// 1 将窗口第一个位置的数据添加到 deque 中,保持递减
deque.push(nums[0])
let i = 1
for (; i < k; i++) {
// - 存在数据
// - 当前数据大于队尾值
// - 出队,再重复比较
while (deque.length && nums[i] > deque[deque.length - 1]) {
deque.pop()
}
deque.push(nums[i])
}
// 将第一个位置的最大值添加到 result
result.push(deque[0])
// 2 遍历后续的数据
const len = nums.length
for (; i < len; i++) {
// 同上进行比较
while (deque.length && nums[i] > deque[deque.length - 1]) {
deque.pop()
}
deque.push(nums[i])
// 检测当前最大值是否位于窗口外
if (deque[0] === nums[i - k]) {
deque.shift()
}
// 添加最大值到 result
result.push(deque[0])
}
return result
};