LeetCode: 641. 设计循环双端队列

73 阅读4分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

641. 设计循环双端队列

来源:力扣(LeetCode)

链接: leetcode.cn/problems/de…

设计实现双端队列。

实现 MyCircularDeque 类:

  • MyCircularDeque(int k) :构造函数,双端队列最大为 k 。
  • boolean insertFront():将一个元素添加到双端队列头部。 如果操作成功返回 true ,否则返回 false 。
  • boolean insertLast() :将一个元素添加到双端队列尾部。如果操作成功返回 true ,否则返回 false 。
  • boolean deleteFront() :从双端队列头部删除一个元素。 如果操作成功返回 true ,否则返回 false 。
  • boolean deleteLast() :从双端队列尾部删除一个元素。如果操作成功返回 true ,否则返回 false 。
  • int getFront():从双端队列头部获得一个元素。如果双端队列为空,返回 -1 。
  • int getRear() :获得双端队列的最后一个元素。 如果双端队列为空,返回 -1 。
  • boolean isEmpty() :若双端队列为空,则返回 true ,否则返回 false 。
  • boolean isFull() :若双端队列满了,则返回 true ,否则返回 false 。

示例 1:

输入
["MyCircularDeque", "insertLast", "insertLast", "insertFront", "insertFront", "getRear", "isFull", "deleteLast", "insertFront", "getFront"]
[[3], [1], [2], [3], [4], [], [], [], [4], []]
输出
[null, true, true, true, false, 2, true, true, true, 4]

解释
MyCircularDeque circularDeque = new MycircularDeque(3); // 设置容量大小为3
circularDeque.insertLast(1);			        // 返回 true
circularDeque.insertLast(2);			        // 返回 true
circularDeque.insertFront(3);			        // 返回 true
circularDeque.insertFront(4);			        // 已经满了,返回 false
circularDeque.getRear();  				// 返回 2
circularDeque.isFull();				        // 返回 true
circularDeque.deleteLast();			        // 返回 true
circularDeque.insertFront(4);			        // 返回 true
circularDeque.getFront();				// 返回 4

提示:

1 <= k <= 1000
0 <= value <= 1000
insertFront, insertLast, deleteFront, deleteLast, getFront, getRear, isEmpty, isFull  调用次数不大于 2000 

解法

  • 列表实现:列表实现双端循环队列,加front表示起点,rear表示最后元素的下一个节点,用于判断是否满了
  • 双链表:front和rear表示起始的头尾节点,无意义;

代码实现

列表实现

使用列表自带的性质; python实现

class MyCircularDeque:

    def __init__(self, k: int):
        self.deque = []
        self.length = 0
        self.max_length = k

    def insertFront(self, value: int) -> bool:
        if self.length < self.max_length:
            self.deque = [value] + self.deque
            self.length += 1
            return True
        return False

    def insertLast(self, value: int) -> bool:
        if self.length < self.max_length:
            self.deque.append(value)
            self.length += 1
            return True
        return False

    def deleteFront(self) -> bool:
        if self.length > 0:
            self.deque.pop(0)
            self.length -= 1
            return True
        return False

    def deleteLast(self) -> bool:
        if self.length > 0:
            self.deque.pop()
            self.length -= 1
            return True
        return False

    def getFront(self) -> int:
        return self.deque[0] if self.length > 0 else -1

    def getRear(self) -> int:
        return self.deque[-1] if self.length > 0 else -1

    def isEmpty(self) -> bool:
        return self.length == 0

    def isFull(self) -> bool:
        return self.length == self.max_length


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

使用front rear双指针,并将容量扩从为k+1

class MyCircularDeque:

    def __init__(self, k: int):
        self.deque = [0] * (k+1)
        self.capacity = k+1
        self.front = 0
        self.rear = 0

    def insertFront(self, value: int) -> bool:
        if self.isFull():
            return False
        self.front -= 1
        self.front += self.capacity
        self.front %= self.capacity
        self.deque[self.front] = value
        return True

    def insertLast(self, value: int) -> bool:
        if self.isFull():
            return False
        self.deque[self.rear] = value
        self.rear += 1
        self.rear += self.capacity
        self.rear %= self.capacity
        return True

    def deleteFront(self) -> bool:
        if self.isEmpty():
            return False
        self.front += 1
        self.front += self.capacity
        self.front %= self.capacity
        return True

    def deleteLast(self) -> bool:
        if self.isEmpty():
            return False
        self.rear -= 1
        self.rear += self.capacity
        self.rear %= self.capacity
        return True

    def getFront(self) -> int:
        return self.deque[self.front] if not self.isEmpty() else -1

    def getRear(self) -> int:
        return self.deque[(self.rear-1+self.capacity)%self.capacity] if not self.isEmpty() else -1

    def isEmpty(self) -> bool:
        return self.front == self.rear

    def isFull(self) -> bool:
        return (self.rear+1) % self.capacity == self.front


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

c++实现

class MyCircularDeque {
private:
    int front = 0;
    int rear = 0;
    int capacity = 0;
    vector<int> deque;
    // 用整型front作为数组的下标,指向队列的前端;用整型rear作为数组的下标,指向队列的尾部+1的位置,即下一个插入的位置


public:
    MyCircularDeque(int k) {
        capacity = k+1;
        deque = vector<int>(k+1, 0);
    }
    
    bool insertFront(int value) {
        if (isFull()) return false;
        front--;
        front += capacity;
        front %= capacity;
        deque[front] = value;
        return true;
    }

    bool insertLast(int value) {
        if (isFull())
            return false;
        deque[rear] = value;
        rear++;
        rear %= capacity;
        return true;
    }
    
    bool deleteFront() {
        if (isEmpty())
            return false;
        front++;
        front %= capacity;
        return true;
    }
    
    bool deleteLast() {
        if (isEmpty())
            return false;
        rear--;
        rear += capacity;
        rear %= capacity;
        return true;
    }
    
    int getFront() {
        if (isEmpty())
            return -1;
        return deque[front];
    }
    
    int getRear() {
        if (isEmpty())
            return -1;
        return deque[(rear-1+capacity)%capacity];
    }
    
    bool isEmpty() {
        return front == rear;
    }
    
    bool isFull() {
        return (rear+1) % capacity == front;
   }
};

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

复杂度分析

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

双链表

python实现

class Node:
    def __init__(self, val=-1, prev_node=None, next_node=None):
        self.val = val
        self.prev = prev_node
        self.next = next_node


class MyCircularDeque(Node):
    def __init__(self, k: int):
        self.size = 0
        self.capacity = k
        self.front = Node(-1)
        self.rear = Node(-1)
        self.front.next = self.rear
        self.rear.prev = self.front  # 双链表

    def insertFront(self, value: int) -> bool:
        if self.isFull():
            return False
        v_node = Node(value)
        next_node = self.front.next
        self.front.next = v_node
        v_node.next = next_node
        v_node.prev = self.front
        next_node.prev = v_node
        self.size += 1
        return True

    def insertLast(self, value: int) -> bool:
        if self.isFull():
            return False
        v_node = Node(value)
        prev_node = self.rear.prev
        v_node.prev = prev_node
        prev_node.next = v_node
        v_node.next = self.rear
        self.rear.prev = v_node
        self.size += 1
        return True

    def deleteFront(self) -> bool:
        if self.isEmpty():
            return False
        v_node = self.front.next
        self.front.next = v_node.next
        self.front.next.prev = self.front
        self.size -= 1
        return True

    def deleteLast(self) -> bool:
        if self.isEmpty():
            return False
        v_node = self.rear.prev
        self.rear.prev = v_node.prev
        self.rear.prev.next = self.rear
        self.size -= 1
        return True

    def getFront(self) -> int:
        return self.front.next.val

    def getRear(self) -> int:
        return self.rear.prev.val

    def isEmpty(self) -> bool:
        return self.size == 0

    def isFull(self) -> bool:
        return self.size == self.capacity



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

c++实现

class Node {
public:
    Node* next;
    Node* prev;
    int val;
    Node(int val) {
        this->val = val;
    }
};


class MyCircularDeque {
public:
    int capacity = 0;
    int size = 0;
    Node* front = new Node(-1);
    Node* rear = new Node(-1);

    MyCircularDeque(int k) {
        capacity = k;
        front->next = rear;
        rear->prev = front;
    }
    
    bool insertFront(int value) {
        if (isFull())
            return false;

        Node* n = new Node(value);
        Node* next = front->next;
        front->next = n;
        n->next = next;
        next->prev = n;
        n->prev = front;
        size++;
        return true;
    }
    
    bool insertLast(int value) {
        if (isFull())
            return false;
        Node* n = new Node(value);
        Node* prev = rear->prev;
        prev->next = n;
        n->prev = prev;
        n->next = rear;
        rear->prev = n;
        size++;
        return true;
    }
    
    bool deleteFront() {
        if (isEmpty())
            return false;
        Node* next = front->next;
        front->next = next->next;
        next->next->prev = front;
        size--;
        delete next;
        return true;
    }
    
    bool deleteLast() {
        if (isEmpty())
            return false;
        Node* prev = rear->prev;
        rear->prev = prev->prev;
        prev->prev->next = rear;
        size--;
        delete prev;
        return true;
    }
    
    int getFront() {
        return front->next->val;
    }
    
    int getRear() {
        return rear->prev->val;
    }
    
    bool isEmpty() {
        return size == 0;
    }
    
    bool isFull() {
        return size == capacity;
    }
};

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

复杂度分析

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