[路飞]_每天刷leetcode_55( 设计双端循环队列 Design Circular Queue)

166 阅读3分钟

「这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战

设计循环双端队列 Design Circular Deque

LeetCode传送门641. 设计循环双端队列

题目

设计实现双端队列。 你的实现需要支持以下操作:

  • MyCircularDeque(k):构造函数,双端队列的大小为k。

  • insertFront():将一个元素添加到双端队列头部。 如果操作成功返回 true。

  • insertLast():将一个元素添加到双端队列尾部。如果操作成功返回 true。

  • deleteFront():从双端队列头部删除一个元素。 如果操作成功返回 true。

  • deleteLast():从双端队列尾部删除一个元素。如果操作成功返回 true。

  • getFront():从双端队列头部获得一个元素。如果双端队列为空,返回 -1。

  • getRear():获得双端队列的最后一个元素。 如果双端队列为空,返回 -1。

  • isEmpty():检查双端队列是否为空。

  • isFull():检查双端队列是否满了。

Design your implementation of the circular double-ended queue (deque).

Implement the MyCircularDeque class:

  • MyCircularDeque(int k) Initializes the deque with a maximum size of k.
  • boolean insertFront() Adds an item at the front of Deque. Returns true if the operation is successful, or false otherwise.
  • boolean insertLast() Adds an item at the rear of Deque. Returns true if the operation is successful, or false otherwise.
  • boolean deleteFront() Deletes an item from the front of Deque. Returns true if the operation is successful, or false otherwise.
  • boolean deleteLast() Deletes an item from the rear of Deque. Returns true if the operation is successful, or false otherwise.
  • int getFront() Returns the front item from the Deque. Returns -1 if the deque is empty.
  • int getRear() Returns the last item from Deque. Returns -1 if the deque is empty.
  • boolean isEmpty() Returns true if the deque is empty, or false otherwise.
  • boolean isFull() Returns true if the deque is full, or false otherwise.

Example:

Input
["MyCircularDeque", "insertLast", "insertLast", "insertFront", "insertFront", "getRear", "isFull", "deleteLast", "insertFront", "getFront"]
[[3], [1], [2], [3], [4], [], [], [], [4], []]
Output
[null, true, true, true, false, 2, true, true, true, 4]

Explanation
MyCircularDeque myCircularDeque = new MyCircularDeque(3);
myCircularDeque.insertLast(1);  // return True
myCircularDeque.insertLast(2);  // return True
myCircularDeque.insertFront(3); // return True
myCircularDeque.insertFront(4); // return False, the queue is full.
myCircularDeque.getRear();      // return 2
myCircularDeque.isFull();       // return True
myCircularDeque.deleteLast();   // return True
myCircularDeque.insertFront(4); // return True
myCircularDeque.getFront();     // return 4

Constraints:

  • 1 <= k <= 1000
  • 0 <= value <= 1000
  • At most 2000 calls will be made to insertFront, insertLast, deleteFront, deleteLast, getFront, getRear, isEmpty, isFull.

思考线


解题思路

本题和上一道题循环队列基本相同,对于相同的内容,在这里不多赘述,不太明白的同学可以去看

// TODO Link

本题我们只专注于两个方法的分析insertFrontdeleteLast.

我们首先来看deleteLast.这个比较简单,我们只需要在 size不为0时,执行size --即可。

最后我们再看一下insertFront.若元素没被排满的情况下,我们要如何放置这个新元素呢?

  • 若此时的head不为0我们只需要让head往前挪动一个位置即可,同时把该位置赋值,最后让size++
  • head ===0 ,我们只要把head挪到数组的最后一个位置len -1即可。

以上就是我们基于循环队列实现的双端循环队列

代码如下:


class MyCircularDeque {
    queue: number[]
    head: number
    size: number
    len: number;
    constructor(k: number) {
        this.len = k;
        this.queue = new Array(k);
        this.size = 0;
        this.head = 0;

    }

    insertFront(value: number): boolean {
        if (this.isFull()) return false;
        if (this.head === 0) {
            this.head = this.len - 1;
            this.queue[this.len - 1] = value;

        } else {
            this.queue[--this.head] = value;
        }
        this.size++;
        return true;

    }

    insertLast(value: number): boolean {
        if (this.isFull()) return false;
        this.queue[(this.head + this.size + this.len) % this.len] = value;
        this.size++;
        return true;
    }

    deleteFront(): boolean {
        if (this.isEmpty()) return false;
        if (this.head === this.len - 1) {
            this.head = 0
        } else {
            this.head++
        };
        this.size--;
        return true;
    }

    deleteLast(): boolean {
        if (this.isEmpty()) return false;
        this.size--;
        return true;
    }

    getFront(): number {
        if (this.isEmpty()) {
            return -1;
        }
        return this.queue[this.head];
    }

    getRear(): number {
        if (this.isEmpty()) {
            return -1;
        }
        return this.queue[(this.head + this.size - 1) % this.len];
    }

    isEmpty(): boolean {
        return this.size === 0;

    }

    isFull(): boolean {
        return this.size === this.len;
    }
}

/**
 * Your MyCircularDeque object will be instantiated and called as such:
 * var obj = new MyCircularDeque(k)
 * var param_1 = obj.insertFront(value)
 * var param_2 = obj.insertLast(value)
 * var param_3 = obj.deleteFront()
 * var param_4 = obj.deleteLast()
 * var param_5 = obj.getFront()
 * var param_6 = obj.getRear()
 * var param_7 = obj.isEmpty()
 * var param_8 = obj.isFull()
 */

时间复杂度

O(1): 在上面的数据结构中,所有的方法都有恒定的时间复杂度。

这就是我对本题的解法,如果有疑问或者更好的解答方式,欢迎留言互动。