Design your implementation of the circular double-ended queue (deque).
Your implementation should support following operations:
MyCircularDeque(k): Constructor, set the size of the deque to be k.insertFront(): Adds an item at the front of Deque. Return true if the operation is successful.insertLast(): Adds an item at the rear of Deque. Return true if the operation is successful.deleteFront(): Deletes an item from the front of Deque. Return true if the operation is successful.deleteLast(): Deletes an item from the rear of Deque. Return true if the operation is successful.getFront(): Gets the front item from the Deque. If the deque is empty, return -1.getRear(): Gets the last item from Deque. If the deque is empty, return -1.isEmpty(): Checks whether Deque is empty or not.isFull(): Checks whether Deque is full or not.
Example:
MyCircularDeque circularDeque = new MycircularDeque(3); // set the size to be 3 circularDeque.insertLast(1); // return true circularDeque.insertLast(2); // return true circularDeque.insertFront(3); // return true circularDeque.insertFront(4); // return false, the queue is full circularDeque.getRear(); // return 2 circularDeque.isFull(); // return true circularDeque.deleteLast(); // return true circularDeque.insertFront(4); // return true circularDeque.getFront(); // return 4
Note:
- All values will be in the range of [0, 1000].
- The number of operations will be in the range of [1, 1000].
- Please do not use the built-in Deque library.
這道題讓我們設計一個環形雙向隊列,由於之前剛做過一道Design Circular Queue,那道設計一個環形隊列,其實跟這道題非常的類似,環形雙向隊列在環形隊列的基礎上多了幾個函數而已,其實本質並沒有啥區別,那么之前那道題的解法一改吧改吧也能用在這道題上,參見代碼如下:
解法一:
class MyCircularDeque { public: /** Initialize your data structure here. Set the size of the deque to be k. */ MyCircularDeque(int k) { size = k; } /** Adds an item at the front of Deque. Return true if the operation is successful. */ bool insertFront(int value) { if (isFull()) return false; data.insert(data.begin(), 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; data.push_back(value); return true; } /** Deletes an item from the front of Deque. Return true if the operation is successful. */ bool deleteFront() { if (isEmpty()) return false; data.erase(data.begin()); return true; } /** Deletes an item from the rear of Deque. Return true if the operation is successful. */ bool deleteLast() { if (isEmpty()) return false; data.pop_back(); return true; } /** Get the front item from the deque. */ int getFront() { if (isEmpty()) return -1; return data.front(); } /** Get the last item from the deque. */ int getRear() { if (isEmpty()) return -1; return data.back(); } /** Checks whether the circular deque is empty or not. */ bool isEmpty() { return data.empty(); } /** Checks whether the circular deque is full or not. */ bool isFull() { return data.size() >= size; } private: vector<int> data; int size; };
就像前一道題中的分析的一樣,上面的解法並不是本題真正想要考察的內容,我們要用上環形Circular的性質,我們除了使用size來記錄環形隊列的最大長度之外,還要使用三個變量,head,tail,cnt,分別來記錄隊首位置,隊尾位置,和當前隊列中數字的個數,這里我們將head初始化為k-1,tail初始化為0。還是從簡單的做起,判空就看當前個數cnt是否為0,判滿就看當前個數cnt是否等於size。接下來取首尾元素,先進行判空,然后根據head和tail分別向后和向前移動一位取即可,記得使用上循環數組的性質,要對size取余。再來看刪除末尾函數,先進行判空,然后tail向前移動一位,使用循環數組的操作,然后cnt自減1。同理,刪除開頭函數,先進行判空,隊首位置head要向后移動一位,同樣進行加1之后對長度取余的操作,然后cnt自減1。再來看插入末尾函數,先進行判滿,然后將新的數字加到當前的tail位置,tail移動到下一位,為了避免越界,我們使用環形數組的經典操作,加1之后對長度取余,然后cnt自增1即可。同樣,插入開頭函數,先進行判滿,然后將新的數字加到當前的head位置,head移動到前一位,然后cnt自增1,參見代碼如下:
解法二:
class MyCircularDeque { public: /** Initialize your data structure here. Set the size of the deque to be k. */ MyCircularDeque(int k) { size = k; head = k - 1; tail = 0, cnt = 0; data.resize(k); } /** Adds an item at the front of Deque. Return true if the operation is successful. */ bool insertFront(int value) { if (isFull()) return false; data[head] = value; head = (head - 1 + size) % size; ++cnt; 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; data[tail] = value; tail = (tail + 1) % size; ++cnt; return true; } /** Deletes an item from the front of Deque. Return true if the operation is successful. */ bool deleteFront() { if (isEmpty()) return false; head = (head + 1) % size; --cnt; return true; } /** Deletes an item from the rear of Deque. Return true if the operation is successful. */ bool deleteLast() { if (isEmpty()) return false; tail = (tail - 1 + size) % size; --cnt; return true; } /** Get the front item from the deque. */ int getFront() { return isEmpty() ? -1 : data[(head + 1) % size]; } /** Get the last item from the deque. */ int getRear() { return isEmpty() ? -1 : data[(tail - 1 + size) % size]; } /** Checks whether the circular deque is empty or not. */ bool isEmpty() { return cnt == 0; } /** Checks whether the circular deque is full or not. */ bool isFull() { return cnt == size; } private: vector<int> data; int size, head, tail, cnt; };
論壇上還見到了使用鏈表來做的解法,由於博主比較抵觸在解法中新建class,所以這里就不貼了,可以參見這個帖子。
類似題目:
參考資料:
https://leetcode.com/problems/design-circular-deque/
