大厂算法面试之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]};