题目描述
设计实现双端队列。
你的实现需要支持以下操作:
MyCircularDeque(k):构造函数,双端队列的大小为k。
insertFront():将一个元素添加到双端队列头部。 如果操作成功返回 true。
insertLast():将一个元素添加到双端队列尾部。如果操作成功返回 true。
deleteFront():从双端队列头部删除一个元素。 如果操作成功返回 true。
deleteLast():从双端队列尾部删除一个元素。如果操作成功返回 true。
getFront():从双端队列头部获得一个元素。如果双端队列为空,返回 -1。
getRear():获得双端队列的最后一个元素。 如果双端队列为空,返回 -1。
isEmpty():检查双端队列是否为空。
isFull():检查双端队列是否满了。
提示:
所有值的范围为 [1, 1000]
操作次数的范围为 [1, 1000]
请不要使用内置的双端队列库。
解题思路一
首先定义一个数组作为存数据的buffer,还需要定义一个容量变量capacity,然后是队首指针front和队尾指针rear。
1、初始化首指针front=0,尾指针rear=0。在队首入队列时,先移动指针,再赋值;而在队尾入队时,先赋值,再移动指针。首尾指针的意义如下:
front:指向队列头部第1个有效数据的位置;
rear:指向队列尾部(即最后 1 个有效数据)的下一个位置,即下一个从队尾入队元素的位置。
2、判断“队列为空”和“队列为满”的条件。为避免两者冲突,特意空出了一个位置,即初始化容量capacity=k+1。
空出一个位置的主要作用是:循环数组中任何时刻一定至少有一个位置不存放有效元素。
这样判别队列为空的条件是:front == rear;
判别队列为满的条件是:(rear + 1) % capacity == front;。
这样就可以理解为,当rear循环到数组的前面,要从后面追上front,还差一格的时候,判定队列为满。
3、因为有循环的出现,要特别注意处理数组下标可能越界的情况。
(1)指针后移的时候,索引+1,要取模((front/rear + 1)%capacity);
(2)指针前移的时候,为了循环到数组的末尾,需要先加上数组的长度,然后再对数组长度取模((front/rear - 1 + capacity)%capacity)。
class MyCircularDeque {
private:
vector<int> buffer;
int capacity;
int front;
int rear;
public:
/** Initialize your data structure here. Set the size of the deque to be k. */
MyCircularDeque(int k) {
capacity = k+1;
buffer.assign(capacity,0);
front = 0;
rear = 0;
}
/** Adds an item at the front of Deque. Return true if the operation is successful. */
bool insertFront(int value) {
if(isFull()) return false;
front = (front-1+capacity)%capacity;
buffer[front] = value;
return true;
}
/** Adds an item at the rear of Deque. Return true if the operation is successful. */
bool insertLast(int value) {
if(isFull()) return false;
buffer[rear] = value;
rear = (rear+1)%capacity;
return true;
}
/** Deletes an item from the front of Deque. Return true if the operation is successful. */
bool deleteFront() {
if(isEmpty()) return false;
front = (front+1)%capacity;
return true;
}
/** Deletes an item from the rear of Deque. Return true if the operation is successful. */
bool deleteLast() {
if(isEmpty()) return false;
rear = (rear-1+capacity)%capacity;
return true;
}
/** Get the front item from the deque. */
int getFront() {
if(isEmpty()) return -1;
return buffer[front];
}
/** Get the last item from the deque. */
int getRear() {
if(isEmpty()) return -1;
return buffer[(rear-1+capacity)%capacity];
}
/** Checks whether the circular deque is empty or not. */
bool isEmpty() {
return rear == front;
}
/** Checks whether the circular deque is full or not. */
bool isFull() {
return front == (rear + 1 )%capacity;
}
};
解题思路二
同样定义一个数组作为存数据的buffer,还需要定义一个容量变量capacity以及一个现在队列中有效元素数量size,然后是队首指针front和队尾指针rear。
1、初始化首指针front=0,尾指针rear=0。在在队首入队列时,先移动指针,再赋值;而在队尾入队时,先赋值,再移动指针。首尾指针的意义如下:
front:指向队列头部第1个有效数据的位置;
rear:指向队列尾部(即最后 1 个有效数据)的下一个位置,即下一个从队尾入队元素的位置。
2、判断“队列为空”和“队列为满”的条件。
这样判别队列为空的条件是:size<1;
判别队列为满的条件是:size == capacity;。
3、同样要特别注意处理数组下标可能越界的情况。
(1)指针后移的时候,索引+1,要取模((front/rear + 1)%capacity);
(2)指针前移的时候,为了循环到数组的末尾,需要先加上数组的长度,然后再对数组长度取模((front/rear - 1 + capacity)%capacity)。
class MyCircularDeque {
private:
vector<int> buffer;
int capacity;
int front;
int rear;
int size;
public:
/** Initialize your data structure here. Set the size of the deque to be k. */
MyCircularDeque(int k) {
capacity = k;
buffer.assign(capacity,0);
front = 0;
rear = 0;
size = 0;
}
/** Adds an item at the front of Deque. Return true if the operation is successful. */
bool insertFront(int value) {
if(isFull()) return false;
front = (front-1+capacity)%capacity;
buffer[front] = value;
++size;
return true;
}
/** Adds an item at the rear of Deque. Return true if the operation is successful. */
bool insertLast(int value) {
if(isFull()) return false;
buffer[rear] = value;
rear = (rear+1)%capacity;
++size;
return true;
}
/** Deletes an item from the front of Deque. Return true if the operation is successful. */
bool deleteFront() {
if(isEmpty()) return false;
front = (front+1)%capacity;
--size;
return true;
}
/** Deletes an item from the rear of Deque. Return true if the operation is successful. */
bool deleteLast() {
if(isEmpty()) return false;
rear = (rear-1+capacity)%capacity;
--size;
return true;
}
/** Get the front item from the deque. */
int getFront() {
if(isEmpty()) return -1;
return buffer[front];
}
/** Get the last item from the deque. */
int getRear() {
if(isEmpty()) return -1;
return buffer[(rear-1+capacity)%capacity];
}
/** Checks whether the circular deque is empty or not. */
bool isEmpty() {
return size < 1;
}
/** Checks whether the circular deque is full or not. */
bool isFull() {
return size == capacity;
}
};