題目描述
設計循環雙端隊列。
解題思路
這道題的前導問題是「力扣」第 622 題:設計循環隊列。在實現上幾乎是一模一樣的,要注意的地方有:
-
在數組裏的操作,我們參考“動態數組”的實現來完成,主要是爲了讓每一步的操作複雜度都最低。只不過不要求我們實現動態擴容與縮容。本題我們需要注意的地方有:
-
定義循環變量
front
和rear
。一直保持這個定義,到底是先賦值還是先移動指針就很容易想清楚了。front
:指向隊列頭部第1
個有效數據的位置;rear
:指向隊列尾部(即最後1
個有效數據)的下一個位置,即下一個從隊尾入隊元素的位置。
(說明:這個定義是依據“動態數組”的定義模仿而來的)
-
爲了避免“隊列爲空”和“隊列爲滿”的判別條件衝突,我們有意浪費了一個位置。
浪費一個位置是指:循環數組中任何時刻一定至少有一個位置不存放有效元素。
- 判別隊列爲空的條件是:
front == rear;
- 判別隊列爲滿的條件是:
(rear + 1) % capacity == front;
。可以這樣理解:當rear
循環到數組的前面,要從後面追上front
,還差一格的時候,即判定隊列爲滿。
- 判別隊列爲空的條件是:
-
因爲有循環的出現,要特別注意處理數組下標可能越界的情況。
- 指針後移的時候,索引
+1
,所以要注意取模。 - 指針前移的時候,爲了防止越界,需要先加上數組的長度,然後再對數組長度取模。
- 指針後移的時候,索引
-
參考代碼
class MyCircularDeque {
private:
vector<int> arr;
int front;
int rear;
int capacity;
public:
/** Initialize your data structure here. Set the size of the deque to be k. */
MyCircularDeque(int k) {
capacity = k + 1;
arr.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;
arr[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;
}
arr[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 被設計在數組的開頭,所以是 +1
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被設計在數組的末尾,所以是 -1
rear = (rear - 1 + capacity) % capacity; // 注:循環隊列的長度爲 (rear - front + capacity) % capacity
return true;
}
/** Get the front item from the deque. */
int getFront() {
if (isEmpty()) {
return -1;
}
return arr[front];
}
/** Get the last item from the deque. */
int getRear() {
if (isEmpty()) {
return -1;
}
// 當rear爲0時,防止數組越界
return arr[(rear - 1 + capacity) % capacity];
}
/** Checks whether the circular deque is empty or not. */
bool isEmpty() {
return front == rear;
}
/** Checks whether the circular deque is full or not. */
bool isFull() {
// 注意:這個設計是非常經典的做法
return (rear + 1) % capacity == front;
}
};