Design your implementation of the circular double-ended queue (deque).
Implement the MyCircularDeque class:
MyCircularDeque(int k)Initializes the deque with a maximum size ofk.boolean insertFront()Adds an item at the front of Deque. Returnstrueif the operation is successful, orfalseotherwise.boolean insertLast()Adds an item at the rear of Deque. Returnstrueif the operation is successful, orfalseotherwise.boolean deleteFront()Deletes an item from the front of Deque. Returnstrueif the operation is successful, orfalseotherwise.boolean deleteLast()Deletes an item from the rear of Deque. Returnstrueif the operation is successful, orfalseotherwise.int getFront()Returns the front item from the Deque. Returns-1if the deque is empty.int getRear()Returns the last item from Deque. Returns-1if the deque is empty.boolean isEmpty()Returnstrueif the deque is empty, orfalseotherwise.boolean isFull()Returnstrueif the deque is full, orfalseotherwise.
Example 1:
Input ["MyCircularDeque", "insertLast", "insertLast", "insertFront", "insertFront", "getRear", "isFull", "deleteLast", "insertFront", "getFront"] [[3], [1], [2], [3], [4], [], [], [], [4], []] Output [null, true, true, true, false, 2, true, true, true, 4] Explanation MyCircularDeque myCircularDeque = new MyCircularDeque(3); myCircularDeque.insertLast(1); // return True myCircularDeque.insertLast(2); // return True myCircularDeque.insertFront(3); // return True myCircularDeque.insertFront(4); // return False, the queue is full. myCircularDeque.getRear(); // return 2 myCircularDeque.isFull(); // return True myCircularDeque.deleteLast(); // return True myCircularDeque.insertFront(4); // return True myCircularDeque.getFront(); // return 4
Constraints:
1 <= k <= 10000 <= value <= 1000- At most
2000calls will be made toinsertFront,insertLast,deleteFront,deleteLast,getFront,getRear,isEmpty,isFull.
Approach 01:
-
C++
-
Python
class MyCircularDeque {
public:
/** Initialize your data structure here. Set the size of the deque to be k. */
MyCircularDeque(int capacity) : capacity(capacity), dequeArray(capacity), rear(capacity - 1) {}
/** 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 + capacity) % capacity;
dequeArray[front] = value;
++currentSize;
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;
rear = ++rear % capacity;
dequeArray[rear] = value;
++currentSize;
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 % capacity;
--currentSize;
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 + capacity) % capacity;
--currentSize;
return true;
}
/** Get the front item from the deque. */
int getFront() {
return isEmpty() ? -1 : dequeArray[front];
}
/** Get the last item from the deque. */
int getRear() {
return isEmpty() ? -1 : dequeArray[rear];
}
/** Checks whether the circular deque is empty or not. */
bool isEmpty() {
return currentSize == 0;
}
/** Checks whether the circular deque is full or not. */
bool isFull() {
return currentSize == capacity;
}
private:
const int capacity; // Capacity of the deque
vector<int> dequeArray; // Array to store deque elements
int currentSize = 0; // Number of elements in the deque
int front = 0; // Index of the front element
int rear; // Index of the rear element
};
class MyCircularDeque:
def __init__(self, capacity: int):
"""Initialize your data structure here. Set the size of the deque to be capacity."""
self.capacity = capacity
self.dequeArray = [0] * capacity
self.size = 0
self.front = 0
self.rear = capacity - 1
def insertFront(self, value: int) -> bool:
"""Adds an item at the front of Deque. Return true if the operation is successful."""
if self.isFull():
return False
self.front = (self.front - 1 + self.capacity) % self.capacity
self.dequeArray[self.front] = value
self.size += 1
return True
def insertLast(self, value: int) -> bool:
"""Adds an item at the rear of Deque. Return true if the operation is successful."""
if self.isFull():
return False
self.rear = (self.rear + 1) % self.capacity
self.dequeArray[self.rear] = value
self.size += 1
return True
def deleteFront(self) -> bool:
"""Deletes an item from the front of Deque. Return true if the operation is successful."""
if self.isEmpty():
return False
self.front = (self.front + 1) % self.capacity
self.size -= 1
return True
def deleteLast(self) -> bool:
"""Deletes an item from the rear of Deque. Return true if the operation is successful."""
if self.isEmpty():
return False
self.rear = (self.rear - 1 + self.capacity) % self.capacity
self.size -= 1
return True
def getFront(self) -> int:
"""Get the front item from the deque."""
return -1 if self.isEmpty() else self.dequeArray[self.front]
def getRear(self) -> int:
"""Get the last item from the deque."""
return -1 if self.isEmpty() else self.dequeArray[self.rear]
def isEmpty(self) -> bool:
"""Checks whether the circular deque is empty or not."""
return self.size == 0
def isFull(self) -> bool:
"""Checks whether the circular deque is full or not."""
return self.size == self.capacity
Time Complexity
- Insert Operations (
insertFrontandinsertLast):Both operations involve updating the
frontorrearpointers and adding an element to the internal array, which are constant-time operations. Hence, both have a time complexity of \(O(1)\). - Delete Operations (
deleteFrontanddeleteLast):These operations involve updating the
frontorrearpointers and adjusting the current size, which are also constant-time operations. Therefore, both have a time complexity of \(O(1)\). - Access Operations (
getFrontandgetRear):Accessing the front or rear element is a direct array access, which takes constant time. Thus, the time complexity for both is \(O(1)\).
- Check Operations (
isEmptyandisFull):Both operations involve a simple comparison, making them constant-time operations with a time complexity of \(O(1)\).
- Overall Time Complexity:
Each operation in the deque (insertion, deletion, access, and check) runs in constant time, resulting in an overall time complexity of \(O(1)\) for all operations.
Space Complexity
- Auxiliary Space:
The space complexity is dominated by the storage required for the internal array
dequeArray, which is used to store the elements of the deque. The size of this array is proportional to the capacity of the deque, resulting in a space complexity of \(O(k)\), wherekis the capacity of the deque. - Overall Space Complexity:
The overall space complexity is \(O(k)\), where
kis the capacity of the deque, as the storage requirement grows linearly with the number of elements that can be stored.