写点什么

大厂算法面试之 leetcode 精讲 18. 队列

作者:全栈潇晨
  • 2021 年 12 月 03 日
  • 本文字数:13039 字

    阅读完需:约 43 分钟

大厂算法面试之 leetcode 精讲 18.队列

视频讲解(高效学习):点击学习

目录:

1.开篇介绍


2.时间空间复杂度


3.动态规划


4.贪心


5.二分查找


6.深度优先&广度优先


7.双指针


8.滑动窗口


9.位运算


10.递归&分治


11剪枝&回溯


12.堆


13.单调栈


14.排序算法


15.链表


16.set&map


17.栈


18.队列


19.数组


20.字符串


21.树


22.字典树


23.并查集


24.其他类型题


  • 队列的特点:先进先出(FIFO)

  • 队列的时间复杂度:入队和出队O(1),查找O(n)

  • 优先队列:priorityQueue,按优先级出队,实现 Heap(Binary,Fibonacci...)

  • js 里没有队列,但是可以用数组模拟


225. 用队列实现栈 (easy)

方法 1.使用两个 Queue 实现
  • 思路:还是考察栈和队列的熟悉程度,没有什么具体的工程实际意义,可以用两个队列来实现栈的功能,但是一个队列的数据导入另一个队列顺序还是没有改变,所以其中一个队列只是用来做备份的,在代码里 queue2 就是备份队列,入栈的时候,队列 1 入队,出栈的时候,如果队列 1 为空,则交换队列 1 和队列 2,为的是将备份队列的元素全部加入队列 1,然后将队列 1 中除了最后一个元素外全部出队,并且加入备份队列,

  • 复杂度分析:push 的时间复杂度为O(1),pop 的时间复杂度为O(n)。空间复杂度O(n),其中 n 是栈内元素的个数,用两个队列来存储


动画过大,点击查看


Js:


var MyStack = function() {    this.queue1 = [];    this.queue2 = [];//备份的队列};
MyStack.prototype.push = function(x) { this.queue1.push(x);};
MyStack.prototype.pop = function() { // 减少两个队列交换的次数, 只有当queue1为空时,交换两个队列 if(!this.queue1.length) { [this.queue1, this.queue2] = [this.queue2, this.queue1]; } while(this.queue1.length > 1) {//当队列1的元素数量大于1的时候不断将元素push进备份队列 this.queue2.push(this.queue1.shift()); } return this.queue1.shift();//最后将队列1最后一个元素出队};
MyStack.prototype.top = function() { const x = this.pop();//查看栈顶,队列出队,然后在push进队列1 this.queue1.push(x); return x;};
MyStack.prototype.empty = function() { return !this.queue1.length && !this.queue2.length;};
复制代码


Java:


class MyStack {    Queue<Integer> queue1;     Queue<Integer> queue2; 
public MyStack() { queue1 = new LinkedList<>(); queue2 = new LinkedList<>(); } public void push(int x) { queue2.offer(x); while (!queue1.isEmpty()){ queue2.offer(queue1.poll()); } Queue<Integer> queueTemp; queueTemp = queue1; queue1 = queue2; queue2 = queueTemp; } public int pop() { return queue1.poll(); }
public int top() { return queue1.peek(); }
public boolean empty() { return queue1.isEmpty(); }}
复制代码
方法 2.使用一个 队列 实现

动画过大,点击查看


  • 思路:使用一个 队列 实现,入栈的时候直接 push 进队列就行,出栈的时候将除了最后一个元素外的元素全部加入到队尾。

  • 复杂度分析:push 的时间复杂度为O(1),pop 的时间复杂度为O(n),空间复杂度O(n)


js:


var MyStack = function() {    this.queue = [];};
MyStack.prototype.push = function(x) { this.queue.push(x);};
MyStack.prototype.pop = function() { let size = this.queue.length; while(size-- > 1) {//将除了最后一个元素外的元素全部加入到队尾。 this.queue.push(this.queue.shift()); } return this.queue.shift();};
MyStack.prototype.top = function() { const x = this.pop();//先出栈,然后在加入队列 this.queue.push(x); return x;};
MyStack.prototype.empty = function() { return !this.queue.length;};
复制代码


java:


class MyStack {    Deque<Integer> queue1;
public MyStack() { queue1 = new ArrayDeque<>(); }
public void push(int x) { queue1.addLast(x); } public int pop() { int size = queue1.size(); size--; while (size-- > 0) { queue1.addLast(queue1.peekFirst()); queue1.pollFirst(); }
int res = queue1.pollFirst(); return res; } public int top() { return queue1.peekLast(); } public boolean empty() { return queue1.isEmpty(); }}
复制代码

703. 数据流中的第 K 大元素 (easy)

方法 1:暴力排序
  • 思路:当数据流有新的元素的时候,重新按升序排序数组,倒数第 k 个元素就是第 k 大的数

  • 复杂度分析:时间复杂度O(c*zlogz),z 为数据流的最长长度,c 为加入元素的个数,排序复杂度是O(zlogz),加入 c 次排序就需要排序 c 次。

方法 2:堆


  • 思路:用一个 size 是 k 的小顶堆来存贮前 k 个元素,堆顶是最小的元素,在循环数组的过程中,不断加入元素然后调整元素在堆中的位置,如果此时优先队列的大小大于 k,我们需要将优先队列的队头元素弹出,以保证优先队列的大小为 k,最后堆顶就是第 K 大元素的位置

  • 复杂度分析:时间复杂度O(nlogk),n 是初始数组的大小,k 是堆的大小,初始堆化和单次插入堆的复杂度都是O(logk),数组的每个数都要插入堆中一次,所以是O(nlogk)。 空间复杂度:O(k), 即堆的大小


js:


var KthLargest = function (k, nums) {    this.k = k;    this.heap = new Heap();    for (const x of nums) {//将数组中的数加入小顶堆        this.add(x);//加入小顶堆    }};
KthLargest.prototype.add = function (val) { this.heap.offer(val);//加入堆 if (this.heap.size() > this.k) {//大小超过了小顶堆的size,就从小顶堆删除一个最小的元素 this.heap.poll();//删除最小的元素 } return this.heap.peek();//返回堆顶};
class Heap { constructor(comparator = (a, b) => a - b, data = []) { this.data = data; this.comparator = comparator;//比较器 this.heapify();//堆化 }
heapify() { if (this.size() < 2) return; for (let i = Math.floor(this.size()/2)-1; i >= 0; i--) { this.bubbleDown(i);//bubbleDown操作 } }
peek() { if (this.size() === 0) return null; return this.data[0];//查看堆顶 }
offer(value) { this.data.push(value);//加入数组 this.bubbleUp(this.size() - 1);//调整加入的元素在小顶堆中的位置 }
poll() { if (this.size() === 0) { return null; } const result = this.data[0]; const last = this.data.pop(); if (this.size() !== 0) { this.data[0] = last;//交换第一个元素和最后一个元素 this.bubbleDown(0);//bubbleDown操作 } return result; }
bubbleUp(index) { while (index > 0) { const parentIndex = (index - 1) >> 1;//父节点的位置 //如果当前元素比父节点的元素小,就交换当前节点和父节点的位置 if (this.comparator(this.data[index], this.data[parentIndex]) < 0) { this.swap(index, parentIndex);//交换自己和父节点的位置 index = parentIndex;//不断向上取父节点进行比较 } else { break;//如果当前元素比父节点的元素大,不需要处理 } } }
bubbleDown(index) { const lastIndex = this.size() - 1;//最后一个节点的位置 while (true) { const leftIndex = index * 2 + 1;//左节点的位置 const rightIndex = index * 2 + 2;//右节点的位置 let findIndex = index;//bubbleDown节点的位置 //找出左右节点中value小的节点 if ( leftIndex <= lastIndex && this.comparator(this.data[leftIndex], this.data[findIndex]) < 0 ) { findIndex = leftIndex; } if ( rightIndex <= lastIndex && this.comparator(this.data[rightIndex], this.data[findIndex]) < 0 ) { findIndex = rightIndex; } if (index !== findIndex) { this.swap(index, findIndex);//交换当前元素和左右节点中value小的 index = findIndex; } else { break; } } }
swap(index1, index2) {//交换堆中两个元素的位置 [this.data[index1], this.data[index2]] = [this.data[index2], this.data[index1]]; }
size() { return this.data.length; }}
复制代码


java:


class KthLargest {    PriorityQueue<Integer> pq;    int k;
public KthLargest(int k, int[] nums) { this.k = k; pq = new PriorityQueue<Integer>(); for (int x : nums) { add(x); } } public int add(int val) { pq.offer(val); if (pq.size() > k) { pq.poll(); } return pq.peek(); }}
复制代码

23. 合并K个升序链表 (hard)

方法 1.分治


  • 思路:自底而上归并,第一次归并 2 个链表,第二次归并 4 个链表...,每次归并不断合并两个有序链表,直到合并完所有分治后的链表

  • 复杂度:时间复杂度O(n * logk),n 是每个链表节点数,k 个链表个数,每次归并,链表数量较少一半,复杂度是O(logk),将两个链表合并成一个顺序链表复杂度是O(2n),所以时间复杂度是 O(n * logk)。空间复杂度是O(logk),即递归的空格复杂度


js:


//自顶而下归并 先分在合var mergeKLists = function (lists) {    // 当是空数组的情况下    if (!lists.length) {        return null;    }    // 合并两个排序链表    const merge = (head1, head2) => {        let dummy = new ListNode(0);        let cur = dummy;        // 新链表,新的值小就先接谁        while (head1 && head2) {            if (head1.val < head2.val) {                cur.next = head1;                head1 = head1.next;            } else {                cur.next = head2;                head2 = head2.next;            }            cur = cur.next;        }        // 如果后面还有剩余的就把剩余的接上        cur.next = head1 == null ? head2 : head1;        return dummy.next;    };    const mergeLists = (lists, start, end) => {        if (start + 1 == end) {            return lists[start];        }        // 输入的k个排序链表,可以分成两部分,前k/2个链表和后k/2个链表        // 如果将这前k/2个链表和后k/2个链表分别合并成两个排序的链表,再将两个排序的链表合并,那么所有链表都合并了        let mid = (start + end) >> 1;        let head1 = mergeLists(lists, start, mid);        let head2 = mergeLists(lists, mid, end);        return merge(head1, head2);    };    return mergeLists(lists, 0, lists.length);};
//自底而上合并var mergeKLists = function (lists) { if (lists.length <= 1) return lists[0] || null;//当归并的节点只有一个时 返回这个节点 const newLists = []; //自底而上归并,第一次归并大小为2的链表,第二次归并大小4的链表... for (let i = 0; i < lists.length; i += 2) { newLists.push(merge(lists[i], lists[i + 1] || null)); } return mergeKLists(newLists);};
const merge = (list_1, list_2) => {//合并两个有序链表 const dummyNode = new ListNode(0); let p = dummyNode;
while (list_1 && list_2) { if (list_1.val < list_2.val) {//先将小的节点加入 p.next = list_1; list_1 = list_1.next; } else { p.next = list_2; list_2 = list_2.next; } p = p.next; }
p.next = list_1 ? list_1 : list_2;//遍历完成还有节点剩余 return dummyNode.next;};
复制代码


java:


class Solution {    public ListNode mergeKLists(ListNode[] lists) {        return mergeLists(lists, 0, lists.length - 1);    }
public ListNode mergeLists(ListNode[] lists, int start, int end) { if (start == end) { return lists[start]; } if (start > end) { return null; } int mid = (start + end) >> 1; return merge(mergeLists(lists, start, mid), mergeLists(lists, mid + 1, end)); }
public ListNode merge(ListNode head1, ListNode head2) { if (head1 == null || head2 == null) { return head1 != null ? head1 : head2; } ListNode dummyNode = new ListNode(0); ListNode cur = dummyNode; while (head1 != null && head2 != null) { if (head1.val < head2.val) { cur.next = head1; head1 = head1.next; } else { cur.next = head2; head2 = head2.next; } cur = cur.next; } cur.next = (head1 != null ? head1 : head2); return dummyNode.next; }}
复制代码
方法 2.优先队列


  • 思路:新建小顶堆,小顶堆的大小是 k,不断从每个链表的头节点开始不断加入小顶堆中,然后取出堆顶值,也就是最小值,然后继续往小顶堆中插入这个最小值在链表的 next 节点

  • 复杂度:时间复杂度O(kn * logk),优先队列的大小是 k,每次插入和删除是O(logk),总共 k * n 的节点个数,每个节点插入删除一次,所以总的复杂度是O(kn*logk)。空间复杂度是O(k),即优先队列的大小


js:


class Heap {    constructor(comparator = (a, b) => a - b, data = []) {        this.data = data;        this.comparator = comparator;//比较器        this.heapify();//堆化    }
heapify() { if (this.size() < 2) return; for (let i = Math.floor(this.size()/2)-1; i >= 0; i--) { this.bubbleDown(i);//bubbleDown操作 } }
peek() { if (this.size() === 0) return null; return this.data[0];//查看堆顶 }
offer(value) { this.data.push(value);//加入数组 this.bubbleUp(this.size() - 1);//调整加入的元素在小顶堆中的位置 }
poll() { if (this.size() === 0) { return null; } const result = this.data[0]; const last = this.data.pop(); if (this.size() !== 0) { this.data[0] = last;//交换第一个元素和最后一个元素 this.bubbleDown(0);//bubbleDown操作 } return result; }
bubbleUp(index) { while (index > 0) { const parentIndex = (index - 1) >> 1;//父节点的位置 //如果当前元素比父节点的元素小,就交换当前节点和父节点的位置 if (this.comparator(this.data[index], this.data[parentIndex]) < 0) { this.swap(index, parentIndex);//交换自己和父节点的位置 index = parentIndex;//不断向上取父节点进行比较 } else { break;//如果当前元素比父节点的元素大,不需要处理 } } }
bubbleDown(index) { const lastIndex = this.size() - 1;//最后一个节点的位置 while (true) { const leftIndex = index * 2 + 1;//左节点的位置 const rightIndex = index * 2 + 2;//右节点的位置 let findIndex = index;//bubbleDown节点的位置 //找出左右节点中value小的节点 if ( leftIndex <= lastIndex && this.comparator(this.data[leftIndex], this.data[findIndex]) < 0 ) { findIndex = leftIndex; } if ( rightIndex <= lastIndex && this.comparator(this.data[rightIndex], this.data[findIndex]) < 0 ) { findIndex = rightIndex; } if (index !== findIndex) { this.swap(index, findIndex);//交换当前元素和左右节点中value小的 index = findIndex; } else { break; } } }
swap(index1, index2) {//交换堆中两个元素的位置 [this.data[index1], this.data[index2]] = [this.data[index2], this.data[index1]]; }
size() { return this.data.length; }}
var mergeKLists = function(lists) { const res = new ListNode(0); let p = res; const h = new Heap(comparator = (a, b) => a.val - b.val); lists.forEach(l => {//插入每个链表的第一个节点 if(l) h.offer(l); }) while(h.size()) {// const n = h.poll();//取出最小值 p.next = n;//最小值加入p的next后 p = p.next;//移动p节点 if(n.next) h.offer(n.next);//插入最小节点的后一个节点 } return res.next;};
复制代码


java:


class Solution {    class Status implements Comparable<Status> {        int val;        ListNode ptr;
Status(int val, ListNode ptr) { this.val = val; this.ptr = ptr; }
public int compareTo(Status status2) { return this.val - status2.val; } }
PriorityQueue<Status> h = new PriorityQueue<Status>();
public ListNode mergeKLists(ListNode[] lists) { for (ListNode node: lists) { if (node != null) { h.offer(new Status(node.val, node)); } } ListNode res = new ListNode(0); ListNode p = res; while (!h.isEmpty()) { Status n = h.poll(); p.next = n.ptr; p = p.next; if (n.ptr.next != null) { h.offer(new Status(n.ptr.next.val, n.ptr.next)); } } return res.next; }}
复制代码

347. 前 K 个高频元素 (medium)

方法 1:优先队列


  • 思路:循环数组,加入小顶堆,当堆的 size 超过 k 时,出堆,循环完成之后,堆中所有的元素就是前 k 大的数字

  • 复杂度:时间复杂度O(nlogk),循环 n 次,每次堆的操作是O(logk)。空间复杂度O(k)


js:


class Heap {    constructor(comparator = (a, b) => a - b, data = []) {        this.data = data;        this.comparator = comparator;//比较器        this.heapify();//堆化    }
heapify() { if (this.size() < 2) return; for (let i = Math.floor(this.size()/2)-1; i >= 0; i--) { this.bubbleDown(i);//bubbleDown操作 } }
peek() { if (this.size() === 0) return null; return this.data[0];//查看堆顶 }
offer(value) { this.data.push(value);//加入数组 this.bubbleUp(this.size() - 1);//调整加入的元素在小顶堆中的位置 }
poll() { if (this.size() === 0) { return null; } const result = this.data[0]; const last = this.data.pop(); if (this.size() !== 0) { this.data[0] = last;//交换第一个元素和最后一个元素 this.bubbleDown(0);//bubbleDown操作 } return result; }
bubbleUp(index) { while (index > 0) { const parentIndex = (index - 1) >> 1;//父节点的位置 //如果当前元素比父节点的元素小,就交换当前节点和父节点的位置 if (this.comparator(this.data[index], this.data[parentIndex]) < 0) { this.swap(index, parentIndex);//交换自己和父节点的位置 index = parentIndex;//不断向上取父节点进行比较 } else { break;//如果当前元素比父节点的元素大,不需要处理 } } }
bubbleDown(index) { const lastIndex = this.size() - 1;//最后一个节点的位置 while (true) { const leftIndex = index * 2 + 1;//左节点的位置 const rightIndex = index * 2 + 2;//右节点的位置 let findIndex = index;//bubbleDown节点的位置 //找出左右节点中value小的节点 if ( leftIndex <= lastIndex && this.comparator(this.data[leftIndex], this.data[findIndex]) < 0 ) { findIndex = leftIndex; } if ( rightIndex <= lastIndex && this.comparator(this.data[rightIndex], this.data[findIndex]) < 0 ) { findIndex = rightIndex; } if (index !== findIndex) { this.swap(index, findIndex);//交换当前元素和左右节点中value小的 index = findIndex; } else { break; } } }
swap(index1, index2) {//交换堆中两个元素的位置 [this.data[index1], this.data[index2]] = [this.data[index2], this.data[index1]]; }
size() { return this.data.length; }}
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 Heap((a, b) => a[1] - b[1]);
//entry 是一个长度为2的数组,0位置存储key,1位置存储value for (const entry of map.entries()) { priorityQueue.offer(entry);//加入堆 if (priorityQueue.size() > k) {//堆的size超过k时,出堆 priorityQueue.poll(); } }
const ret = [];
for (let i = priorityQueue.size() - 1; i >= 0; i--) {//取出前k大的数 ret[i] = priorityQueue.poll()[0]; }
return ret;};
复制代码


java:


class Solution {    public int[] topKFrequent(int[] nums, int k) {        int[] ret = new int[k];        HashMap<Integer, Integer> map = new HashMap<>();        for (int num : nums) {            map.put(num, map.getOrDefault(num, 0) + 1);        }
Set<Map.Entry<Integer, Integer>> entries = map.entrySet(); PriorityQueue<Map.Entry<Integer, Integer>> priorityQueue = new PriorityQueue<>((o1, o2) -> o1.getValue() - o2.getValue()); for (Map.Entry<Integer, Integer> entry : entries) { priorityQueue.offer(entry); if (priorityQueue.size() > k) { priorityQueue.poll(); } } for (int i = k - 1; i >= 0; i--) { ret[i] = priorityQueue.poll().getKey(); } return ret; }}
复制代码

692. 前K个高频单词(medium)

方法 1:排序

js:


var topKFrequent = function (words, k) {    const map = {};    words.forEach(v => map[v] = (map[v] || 0) + 1);    const keys = Object.keys(map).sort((a, b) => map[b] - map[a] || a.localeCompare(b))    return keys.slice(0, k);};
复制代码
方法 2:堆

js:


class Heap {    constructor(comparator = (a, b) => a - b, data = []) {        this.data = data;        this.comparator = comparator;//比较器        this.heapify();//堆化    }
heapify() { if (this.size() < 2) return; for (let i = Math.floor(this.size()/2)-1; i >= 0; i--) { this.bubbleDown(i);//bubbleDown操作 } }
peek() { if (this.size() === 0) return null; return this.data[0];//查看堆顶 }
offer(value) { this.data.push(value);//加入数组 this.bubbleUp(this.size() - 1);//调整加入的元素在小顶堆中的位置 }
poll() { if (this.size() === 0) { return null; } const result = this.data[0]; const last = this.data.pop(); if (this.size() !== 0) { this.data[0] = last;//交换第一个元素和最后一个元素 this.bubbleDown(0);//bubbleDown操作 } return result; }
bubbleUp(index) { while (index > 0) { const parentIndex = (index - 1) >> 1;//父节点的位置 //如果当前元素比父节点的元素小,就交换当前节点和父节点的位置 if (this.comparator(this.data[index], this.data[parentIndex]) < 0) { this.swap(index, parentIndex);//交换自己和父节点的位置 index = parentIndex;//不断向上取父节点进行比较 } else { break;//如果当前元素比父节点的元素大,不需要处理 } } }
bubbleDown(index) { const lastIndex = this.size() - 1;//最后一个节点的位置 while (true) { const leftIndex = index * 2 + 1;//左节点的位置 const rightIndex = index * 2 + 2;//右节点的位置 let findIndex = index;//bubbleDown节点的位置 //找出左右节点中value小的节点 if ( leftIndex <= lastIndex && this.comparator(this.data[leftIndex], this.data[findIndex]) < 0 ) { findIndex = leftIndex; } if ( rightIndex <= lastIndex && this.comparator(this.data[rightIndex], this.data[findIndex]) < 0 ) { findIndex = rightIndex; } if (index !== findIndex) { this.swap(index, findIndex);//交换当前元素和左右节点中value小的 index = findIndex; } else { break; } } }
swap(index1, index2) {//交换堆中两个元素的位置 [this.data[index1], this.data[index2]] = [this.data[index2], this.data[index1]]; }
size() { return this.data.length; }}
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 Heap((a, b) => { return a[1] === b[1] ? b[0].localeCompare(a[0]) : a[1] - b[1] });
//entry 是一个长度为2的数组,0位置存储key,1位置存储value for (const entry of map.entries()) { priorityQueue.offer(entry);//加入堆 if (priorityQueue.size() > k) {//堆的size超过k时,出堆 priorityQueue.poll(); } }
const ret = [];
for (let i = priorityQueue.size() - 1; i >= 0; i--) {//取出前k大的数 ret[i] = priorityQueue.poll()[0]; }
return ret;};
复制代码

933. 最近的请求次数 (easy)

  • 思路:将请求加入队列,如果队头元素请求的时间在[t-3000,t]之外 就不断出队

  • 复杂度:时间复杂度O(q),q 是 ping 的次数。空间复杂度O(w),w 是队列中最多的元素个数


js:


var RecentCounter = function() {    this.queue = []};
RecentCounter.prototype.ping = function(t) { this.queue.push(t);//新请求入队 const time = t-3000;//计算3000ms前的时间 while(this.queue[0] < time){//如果队头元素请求的时间在[t-3000,t]之外 就不断出队 this.queue.shift(); } return this.queue.length;//在[t-3000,t]区间内队列剩余的元素就是符合要求的请求数};
复制代码


java:


class RecentCounter {    Queue<Integer> q;    public RecentCounter() {        q = new LinkedList();    }
public int ping(int t) { q.add(t); while (q.peek() < t - 3000) q.poll(); return q.size(); }}
复制代码

622. 设计循环队列 (medium)

  • 复杂度:时间复杂度O(1),空间复杂度O(k)



js:


var MyCircularQueue = function(k) {    this.front = 0    this.rear = 0    this.max = k    this.list = Array(k)};
MyCircularQueue.prototype.enQueue = function(value) { if(this.isFull()) { return false } else { this.list[this.rear] = value this.rear = (this.rear + 1) % this.max return true }};
MyCircularQueue.prototype.deQueue = function() { let v = this.list[this.front] this.list[this.front] = undefined if(v !== undefined ) { this.front = (this.front + 1) % this.max return true } else { return false }};
MyCircularQueue.prototype.Front = function() { if(this.list[this.front] === undefined) { return -1 } else { return this.list[this.front] }};
MyCircularQueue.prototype.Rear = function() { let rear = this.rear - 1 if(this.list[rear < 0 ? this.max - 1 : rear] === undefined) { return -1 } else { return this.list[rear < 0 ? this.max - 1 : rear] }};
MyCircularQueue.prototype.isEmpty = function() { return this.front === this.rear && !this.list[this.front]};
MyCircularQueue.prototype.isFull = function() { return (this.front === this.rear) && !!this.list[this.front]};
复制代码


用户头像

全栈潇晨

关注

还未添加个人签名 2021.02.17 加入

还未添加个人简介

评论

发布
暂无评论
大厂算法面试之leetcode精讲18.队列