Design your implementation of the circular queue. The circular queue is a linear data structure in which the operations are performed based on FIFO (First In First Out) principle and the last position is connected back to the first position to make a circle. It is also called "Ring Buffer".html
One of the benefits of the circular queue is that we can make use of the spaces in front of the queue. In a normal queue, once the queue becomes full, we cannot insert the next element even if there is a space in front of the queue. But using the circular queue, we can use the space to store new values.數組
Your implementation should support following operations:函數
MyCircularQueue(k)
: Constructor, set the size of the queue to be k.Front
: Get the front item from the queue. If the queue is empty, return -1.Rear
: Get the last item from the queue. If the queue is empty, return -1.enQueue(value)
: Insert an element into the circular queue. Return true if the operation is successful.deQueue()
: Delete an element from the circular queue. Return true if the operation is successful.isEmpty()
: Checks whether the circular queue is empty or not.isFull()
: Checks whether the circular queue is full or not.
Example:post
MyCircularQueue circularQueue = new MyCircularQueue(3); // set the size to be 3 circularQueue.enQueue(1); // return true circularQueue.enQueue(2); // return true circularQueue.enQueue(3); // return true circularQueue.enQueue(4); // return false, the queue is full circularQueue.Rear(); // return 3 circularQueue.isFull(); // return true circularQueue.deQueue(); // return true circularQueue.enQueue(4); // return true circularQueue.Rear(); // return 4
Note:ui
這道題讓咱們設計一個環形的隊列,說是不能使用內置的 queue 類,而且讓咱們實現一系列的成員函數,如進隊,出隊,取首尾元素,以及判空,判滿等等。那麼博主最早想到的就是用一個數組 data 來實現,而且用一個變量 size 來保存咱們的環形隊列的大小。先來實現最簡單的判空和判滿函數吧,判空就是判斷 data 數組是否爲空,判滿就是看 data 數組的大小是否等於 size。而後是取首尾元素,須要先對數組判空,而後取首尾元素便可。進隊列函數先要判滿,而後加入 data 數組,出隊列函數,先要判空,而後去掉數組的首元素便可,參見代碼以下:url
解法一:spa
class MyCircularQueue { public: MyCircularQueue(int k) { size = k; } bool enQueue(int value) { if (isFull()) return false; data.push_back(value); return true; } bool deQueue() { if (isEmpty()) return false; data.erase(data.begin()); return true; } int Front() { if (isEmpty()) return -1; return data.front(); } int Rear() { if (isEmpty()) return -1; return data.back(); } bool isEmpty() { return data.empty(); } bool isFull() { return data.size() >= size; } private: vector<int> data; int size; };
作完上面的方法有沒有一種感受,這跟環形 Circular 有毛線關係,還有題目要求中的第二段話裏的「咱們可使用隊列前面的空間」,徹底沒有用到啊。其實上面的解法並非本題真正想要考察的內容,咱們要用上環形 Circular 的性質,以前咱們貌似應該作過環形數組的題目吧,提到環形數組,博主最早想到的就是座標加1,再對數組長度取餘。這是數組可以環形的關鍵,那麼這裏也同樣,咱們除了使用 size 來記錄環形隊列的最大長度以外,還要使用三個變量,head,tail,cnt,分別來記錄隊首位置,隊尾位置,和當前隊列中數字的個數,這裏咱們將head初始化爲 0,tail初始化爲 k-1,head 是指向數組範圍內的起始位置,tail 指向數組範圍內的結束位置。那麼在 Front() 函數,因爲咱們要返回起始位置的數字,爲了避免越界,進行環形走位,還要對 size 取餘,因而就變成了 head % size,同理,對於 Rear() 函數,咱們要返回結束位置的數字,爲了避免越界,而且環形走位,tail 要先加上size,再對 size 取餘,因而就變成了 (tail+size) % size。設計
仍是從簡單的作起,判空就看當前個數 cnt 是否爲0,判滿就看當前個數 cnt 是否等於 size。接下來取首尾元素,先進行判空,而後根據 head 和tail 取便可,記得使用上循環數組的性質,要對 size 取餘。再來看進隊列函數,先進行判滿,tail 要移動到下一位,爲了不越界,咱們使用環形數組的經典操做,加1以後對長度取餘,而後將新的數字加到當前的tail位置,cnt 再自增1便可。一樣,出隊列函數先進行判空,隊首位置 head 要向後移動一位,一樣進行加1以後對長度取餘的操做,到這裏就能夠了,不用真正的去刪除數字,由於 head 和 tail 限定了咱們的當前隊列的範圍,而後 cnt 自減1,參見代碼以下:code
解法二:orm
class MyCircularQueue { public: MyCircularQueue(int k) { size = k; head = k - 1; tail = 0; cnt = 0; data.resize(k); } bool enQueue(int value) { if (isFull()) return false; data[tail] = value; tail = (tail + 1) % size; ++cnt; return true; } bool deQueue() { if (isEmpty()) return false; head = (head + 1) % size; --cnt; return true; } int Front() { return isEmpty() ? -1 : data[(head + 1) % size]; } int Rear() { return isEmpty() ? -1 : data[(tail - 1 + size) % size]; } bool isEmpty() { return cnt == 0; } bool isFull() { return cnt == size; } private: vector<int> data; int size, cnt, head, tail; };
論壇上還見到了使用鏈表來作的解法,因爲博主比較抵觸在解法中新建class,因此這裏就不貼了,能夠參見這個帖子。
相似題目:
參考資料:
https://leetcode.com/problems/design-circular-queue/
https://leetcode.com/problems/design-circular-queue/discuss/149420/Concise-Java-using-array
https://leetcode.com/problems/design-circular-queue/discuss/162759/JAVA-Pass-All-Test-Cases-100-O(1)