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".
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.
Implement the MyCircularQueue
class:
MyCircularQueue(k)
Initializes the object with the size of the queue to be k
.int Front()
Gets the front item from the queue. If the queue is empty, return -1
.int Rear()
Gets the last item from the queue. If the queue is empty, return -1
.boolean enQueue(int value)
Inserts an element into the circular queue. Return true
if the operation is successful.boolean deQueue()
Deletes an element from the circular queue. Return true
if the operation is successful.boolean isEmpty()
Checks whether the circular queue is empty or not.boolean isFull()
Checks whether the circular queue is full or not.You must solve the problem without using the built-in queue data structure in your programming language.
Example 1:
Input ["MyCircularQueue", "enQueue", "enQueue", "enQueue", "enQueue", "Rear", "isFull", "deQueue", "enQueue", "Rear"] [[3], [1], [2], [3], [4], [], [], [], [4], []] Output [null, true, true, true, false, 3, true, true, true, 4] Explanation MyCircularQueue myCircularQueue = new MyCircularQueue(3); myCircularQueue.enQueue(1); // return True myCircularQueue.enQueue(2); // return True myCircularQueue.enQueue(3); // return True myCircularQueue.enQueue(4); // return False myCircularQueue.Rear(); // return 3 myCircularQueue.isFull(); // return True myCircularQueue.deQueue(); // return True myCircularQueue.enQueue(4); // return True myCircularQueue.Rear(); // return 4
Constraints:
1 <= k <= 1000
0 <= value <= 1000
3000
calls will be made to enQueue
, deQueue
, Front
, Rear
, isEmpty
, and isFull
.This problem requires designing a circular queue data structure. A circular queue is a linear data structure that uses a FIFO (First-In, First-Out) principle, but unlike a standard queue, it reuses space at the beginning of the queue once the end is reached, forming a circular buffer.
The most efficient way to implement a circular queue is using an array. We'll track:
q
(array): Stores the queue elements.front
(integer): Index of the front element (the next element to be dequeued).size
(integer): Number of elements currently in the queue.capacity
(integer): Maximum capacity of the queue.Methods:
__init__(k)
(Constructor): Initializes the queue with capacity k
.
enQueue(value)
: Adds an element to the rear of the queue.
isFull()
). If full, returns false
.(front + size) % capacity
(using the modulo operator to wrap around the array for circularity), increments size
, and returns true
.deQueue()
: Removes and returns the element at the front of the queue.
isEmpty()
). If empty, returns false
.front
(modulo capacity
for circularity), decrements size
, and returns true
.Front()
: Returns the value of the front element.
-1
.q[front]
.Rear()
: Returns the value of the rear element.
-1
.q[(front + size - 1) % capacity]
.isEmpty()
: Checks if the queue is empty (size == 0
).
isFull()
: Checks if the queue is full (size == capacity
).
Time Complexity: All operations (enQueue
, deQueue
, Front
, Rear
, isEmpty
, isFull
) have a time complexity of O(1) because they involve constant-time array access and arithmetic operations.
Space Complexity: O(k), where k is the queue's capacity, due to the array used to store the elements.
The code examples in various languages are provided in the original response. They all implement the array-based approach described above. The key is to correctly handle the circularity using the modulo operator (%
) to wrap around the array when accessing indices. Each example uses slightly different naming conventions and syntax but embodies the same underlying algorithm.